home *** CD-ROM | disk | FTP | other *** search
/ Deutsche Edition 1 / Deutsche Edition 1.iso / amok / 081-090 / amok85 / termite / termite.mod < prev    next >
Text File  |  1993-11-04  |  82KB  |  2,486 lines

  1. (*----------------------------------------------------------------------------
  2.  :Program.     Termite.mod
  3.  :Contents.    A little Terminal Proggy (OS 2.04 or higher)
  4.  :Author.      Christian Stiens
  5.  :Address.     Snail-Mail:           E-Mail:
  6.  :Address.     Heustiege 2           FIDO: 2:245/5802.25
  7.  :Address.     W-4710 Lüdinghausen   UUCP: Christian_Stiens@ouzonix.bo.open.de
  8.  :Copyright.   SHAREWARE (DM 10)
  9.  :Language.    Oberon-2
  10.  :Translator.  Amiga Oberon 2.45
  11.  :History.     V1.0, 25-Jan-93: first release
  12.  :Imports.     CBText37, DeviceSupport37, FileReq37, OwnDevUnit,
  13.  :Imports.     ReqTools, XPR
  14.  :Support.     Thanks to Nico Francois for his ReqTools Library
  15.  :Support.     Thanks to Christopher A. Wichura for his OwnDevUnit Library
  16.  :Support.     Thanks to Olaf `Olsen' Barthel for releasing the source of term
  17. ----------------------------------------------------------------------------*)
  18.  
  19.  
  20. (* $Debug- *)
  21.  
  22. MODULE Termite;
  23.  
  24.   IMPORT
  25.            Arguments,  (* To set the correct CurrentDir if WB-started *)
  26.     cbt := CBText37,
  27.     con := Console,
  28.     cu  := ConUnit,
  29.     d   := Dos,
  30.     df  := DiskFont,
  31.     ds  := DeviceSupport37,
  32.     e   := Exec,
  33.     fr  := FileReq37,
  34.     fs  := FileSystem, (* modified: BufSize = 8192 *)
  35.     g   := Graphics,
  36.     gt  := GadTools,
  37.     hw  := Hardware,
  38.     I   := Intuition,
  39.     ie  := InputEvent,
  40.     in  := Input,
  41.     k   := KeyMap,
  42.          (* $IF debug *)
  43.            NoGuru,
  44.          (* $END *)
  45.     ol  := OberonLib,
  46.     odu := OwnDevUnit,
  47.     rt  := ReqTools,
  48.     se  := Serial,
  49.     SYS := SYSTEM,
  50.     str := Strings,
  51.     ti  := Timer,
  52.     u   := Utility,
  53.            XPR;
  54.  
  55.  
  56.   TYPE
  57.     LongArray12=ARRAY 12 OF LONGINT;
  58.     LongArray8 =ARRAY  8 OF LONGINT;
  59.  
  60.   CONST
  61.     version = "\o$VER: termite 1.0 (25.1.93)";
  62.  
  63.     baudRates = LongArray12(112,300,1200,2400,4800,9600,19200,31250,38400,57600,76800,115200);
  64.     bufSizes  = LongArray8 (512,1024,2048,4096,8192,16384,32768,65536);
  65.  
  66.     topaz80attr = g.TextAttr(SYS.ADR("topaz.font"),8,SHORTSET{},SHORTSET{});
  67.  
  68.     A5 = 13;
  69.  
  70.  
  71.   TYPE
  72.  
  73.     Config = STRUCT
  74.       device        : e.STRING;
  75.       unit          : INTEGER;
  76.       rBufLen       : LONGINT;
  77.       baud          : LONGINT;
  78.       breakTime     : LONGINT;
  79.       bitsPerChar   : SHORTINT;
  80.       stopBits      : SHORTINT;
  81.       parity        : SHORTINT;
  82.       handShaking   : SHORTINT;
  83.       duplex        : SHORTINT;
  84.       radBoogie     : BOOLEAN;
  85.       initString    : e.STRING;
  86.       hangupString  : e.STRING;
  87.       time4connect  : LONGINT;
  88.       capture       : e.STRING;
  89.       protocol      : e.STRING;
  90.       uploadDir     : e.STRING;
  91.       downloadDir   : e.STRING;
  92.       pasteDir      : e.STRING;
  93.       pasteDelay    : LONGINT;
  94.       screenDepth   : INTEGER;
  95.       font          : e.STRING;
  96.       keyMap        : e.STRING;
  97.       priority      : SHORTINT;
  98.     END;
  99.  
  100.  
  101.   CONST
  102.     none       = 0;
  103.  
  104.     xonxoff    = 1;
  105.     ctsrts     = 2;
  106.  
  107.     even       = 1;
  108.     odd        = 2;
  109.     mark       = 3;
  110.     space      = 4;
  111.  
  112.     halfduplex = 0;
  113.     fullduplex = 1;
  114.  
  115.  
  116.   CONST
  117.     writeBufLen = 256;
  118.     readBufLen = 1024;
  119.     maxDialEntries = 40;
  120.     items = 77;
  121.  
  122.  
  123.   TYPE
  124.     NewMenuType     = ARRAY items                OF gt.NewMenu;
  125.     FullNewMenuType = ARRAY items+maxDialEntries OF gt.NewMenu;
  126.  
  127.  
  128.   VAR
  129.     oldMemReqs    : LONGSET;
  130.     resident      : BOOLEAN;
  131.     serWriteReq   : se.IOExtSerPtr;
  132.     serReadReq    : se.IOExtSerPtr;
  133.     serReadPort   : e.MsgPortPtr;
  134.     serReq        : se.IOExtSerPtr;
  135.     writeBuf      : UNTRACED POINTER TO ARRAY writeBufLen OF CHAR;
  136.     readBuf       : UNTRACED POINTER TO ARRAY readBufLen OF CHAR;
  137.     conWriteReq   : e.IOStdReqPtr;
  138.     conReadReq    : e.IOStdReqPtr;
  139.     conReadPort   : e.MsgPortPtr;
  140.     timeReq       : ti.TimeRequestPtr;
  141.     inputReq      : e.IOStdReqPtr;
  142.     xprio         : XPR.IOPtr;
  143.     me            : d.ProcessPtr;
  144.     scr           : I.ScreenPtr;
  145.     height        : INTEGER;
  146.     args          : STRUCT config,phonebook: e.STRPTR END;
  147.     rd            : d.RDArgsPtr;
  148.     pub           : I.ScreenPtr;
  149.     attr          : g.TextAttrPtr;
  150.     font          : g.TextFontPtr;
  151.     rect          : g.Rectangle;
  152.     menu          : I.MenuPtr;
  153.     newMenu       : FullNewMenuType;
  154.     config        : Config;
  155.     win           : I.WindowPtr;
  156.     blockCnt      : INTEGER;
  157.     transferWin   : I.WindowPtr;
  158.     topaz80       : g.TextFontPtr;
  159.     statusWin     : I.WindowPtr;
  160.     statusTask    : e.TaskPtr;
  161.     statusStack   : UNTRACED POINTER TO ARRAY 4008 OF SYS.BYTE;
  162.     statusRunning : BOOLEAN;
  163.     colorMap      : ARRAY 32 OF INTEGER;
  164.     colorCnt      : INTEGER;
  165.     mySig         : SHORTINT;
  166.     dialArray     : ARRAY maxDialEntries OF e.STRPTR;
  167.     lastDialNr    : INTEGER;
  168.     afpt          : ARRAY 2 OF INTEGER;
  169.     bbox          : I.IBox;
  170.     lock          : d.FileLockPtr;
  171.     seg           : e.BPTR;
  172.     oldPri        : LONGINT;
  173.     keyMap        : k.KeyMapPtr;
  174.     oldWP         : I.WindowPtr;
  175.     xprFlags      : LONGSET;
  176.     serLocked     : BOOLEAN;
  177.     reading       : BOOLEAN;
  178.     online        : BOOLEAN;
  179.     protocolOpts  : e.STRING;
  180.     vi            : e.APTR;
  181.     displayID     : LONGINT;
  182.     capture       : fs.File;
  183.     cap           : BOOLEAN;
  184.     sigRec        : LONGSET;
  185.     sigMask       : LONGSET;
  186.     msg           : I.IntuiMessagePtr;
  187.     ySize         : INTEGER;
  188.     ioErr         : INTEGER;
  189.     i             : INTEGER;
  190.     n             : LONGINT;
  191.     name          : e.STRING;
  192.     (* $IF unreg *)
  193.     factors       : STRUCT a,b: INTEGER END;
  194.     string        : e.STRING;
  195.     result        : LONGINT;
  196.     (* $END *)
  197.  
  198.  
  199.   PROCEDURE SerInit(ser: e.MessagePtr);
  200.   BEGIN
  201.     INCL(ser(se.IOExtSer).serFlags,se.shared);
  202.   END SerInit;
  203.  
  204.  
  205.   PROCEDURE ConInit(con: e.MessagePtr);
  206.   BEGIN
  207.     con(e.IOStdReq).data := win;
  208.     con(e.IOStdReq).length := SIZE(I.Window);
  209.   END ConInit;
  210.  
  211.  
  212.   PROCEDURE Min(x,y: LONGINT): LONGINT;
  213.   BEGIN
  214.     IF x < y THEN RETURN x ELSE RETURN y END;
  215.   END Min;
  216.  
  217.  
  218.   PROCEDURE StringToInt(st: ARRAY OF CHAR; base: INTEGER): LONGINT; (* $CopyArrays- *)
  219.     VAR i,sum,n: LONGINT;
  220.         ch: CHAR;
  221.   BEGIN
  222.     sum := 0;
  223.     IF st[0]="$" THEN base := 16 END;
  224.     FOR i := 0 TO str.Length(st)-1 DO
  225.       ch := CAP(st[i]);
  226.       CASE ch OF
  227.       | "0".."9": n := ORD(ch)-ORD("0")
  228.       | "A".."Z": IF base=16 THEN n := ORD(ch)-ORD("A")+10 ELSE n := -1 END;
  229.       ELSE
  230.         n := -1;
  231.       END;
  232.       IF (n>=0) & (sum<100000000) THEN sum := sum*base+n END;
  233.     END;
  234.     RETURN sum;
  235.   END StringToInt;
  236.  
  237.  
  238.   PROCEDURE LoadKeyMap(name: ARRAY OF CHAR): k.KeyMapPtr; (* $CopyArrays- *)
  239.     VAR keyMap: k.KeyMapPtr;
  240.         newSeg: e.BPTR;
  241.         fileName: e.STRING;
  242.   BEGIN
  243.     keyMap := NIL;
  244.     IF name[0]#0X THEN
  245.       IF (str.Occurs(name,":") >= 0) OR (str.Occurs(name,"/") >= 0) THEN
  246.         COPY(name,fileName);
  247.       ELSE
  248.         fileName := "DEVS:keymaps/";
  249.         IF d.AddPart(fileName,name,LEN(fileName)) THEN END;
  250.       END;
  251.       newSeg := d.LoadSeg(fileName);
  252.       IF newSeg # NIL THEN
  253.         IF seg # NIL THEN d.UnLoadSeg(seg) END;
  254.         seg := newSeg;
  255.         keyMap := SYS.VAL(e.APTR,SYS.VAL(LONGINT,newSeg)*4+4+SIZE(e.Node));
  256.       END;
  257.     END;
  258.     RETURN keyMap;
  259.   END LoadKeyMap;
  260.  
  261.  
  262.   PROCEDURE BlockWindow;
  263.   BEGIN
  264.     IF win#NIL THEN
  265.       IF blockCnt=0 THEN
  266.         I.ClearMenuStrip(win);
  267.         rt.SetWaitPointer(win);
  268.       END;
  269.       INC(blockCnt);
  270.     END;
  271.   END BlockWindow;
  272.  
  273.  
  274.   PROCEDURE UnBlockWindow;
  275.   BEGIN
  276.     IF win#NIL THEN
  277.       DEC(blockCnt);
  278.       IF blockCnt=0 THEN
  279.         I.ClearPointer(win);
  280.         IF I.ResetMenuStrip(win,menu^) THEN END;
  281.       END;
  282.     END;
  283.   END UnBlockWindow;
  284.  
  285.  
  286.   PROCEDURE RemSpaces(VAR s: ARRAY OF CHAR): BOOLEAN;
  287.     VAR i: LONGINT;
  288.         quote: BOOLEAN;
  289.   BEGIN
  290.     quote := FALSE;
  291.     FOR i := 0 TO str.Length(s)-1 DO
  292.       IF  s[i]='"' THEN quote := ~quote END;
  293.       IF (s[i]=";") & ~quote THEN s[i] := 0X END;
  294.     END;
  295.     WHILE (str.Length(s)>0) & ((s[0]=" ") OR (s[0]="\t")) DO str.Delete(s,0,1) END;
  296.     i := str.Length(s)-1;
  297.     WHILE (i>=0) & ((s[i]=" ") OR (s[i]="\t")) DO
  298.       s[i] := 0X;
  299.       DEC(i);
  300.     END;
  301.     RETURN s[0]#0X
  302.   END RemSpaces;
  303.  
  304.  
  305.   PROCEDURE SendReadReq;
  306.   BEGIN
  307.     IF ~reading THEN
  308.       serReadReq.ioSer.data    := readBuf;
  309.       serReadReq.ioSer.length  := 1;
  310.       serReadReq.ioSer.command := e.read;
  311.       SYS.SETREG(0,e.SetSignal(LONGSET{},LONGSET{serReadPort.sigBit}));
  312.       e.SendIO(serReadReq);
  313.       reading := TRUE;
  314.     END;
  315.   END SendReadReq;
  316.  
  317.  
  318.   PROCEDURE AbortReadReq;
  319.   BEGIN
  320.     IF reading THEN
  321.       IF e.CheckIO(serReadReq)=NIL THEN
  322.         e.AbortIO(serReadReq);
  323.       END;
  324.       e.OldWaitIO(serReadReq);
  325.       reading := FALSE
  326.     END;
  327.   END AbortReadReq;
  328.  
  329.  
  330.   PROCEDURE Capture(block: e.APTR; size: LONGINT);
  331.   BEGIN
  332.     IF cap & (capture.status=fs.ok) THEN
  333.       SYS.SETREG(0,fs.WriteBlock(capture,block,size));
  334.     END;
  335.   END Capture;
  336.  
  337.  
  338.   PROCEDURE ConfigToSer;
  339.     VAR wasReading: BOOLEAN;
  340.   BEGIN
  341.     wasReading := reading;
  342.     AbortReadReq;
  343.     serWriteReq.serFlags := SHORTSET{se.xDisabled,se.partyOn};
  344.     serWriteReq.extFlags := LONGSET{};
  345.     serWriteReq.baud     := config.baud;
  346.     serWriteReq.rBufLen  := config.rBufLen;
  347.     serWriteReq.writeLen := config.bitsPerChar;
  348.     serWriteReq.readLen  := config.bitsPerChar;
  349.     serWriteReq.stopBits := config.stopBits;
  350.     serWriteReq.brkTime  := config.breakTime;
  351.     CASE config.handShaking OF
  352.     | xonxoff: EXCL(serWriteReq.serFlags,se.xDisabled);
  353.     | ctsrts:  INCL(serWriteReq.serFlags,se.sevenWire);
  354.     ELSE
  355.     END;
  356.     CASE config.parity OF
  357.     | none:  EXCL(serWriteReq.serFlags,se.partyOn)
  358.     | even:
  359.     | odd:   INCL(serWriteReq.serFlags,se.partyOdd);
  360.     | mark:  INCL(serWriteReq.extFlags,se.mSpOn);   INCL(serWriteReq.extFlags,se.mark);
  361.     | space: INCL(serWriteReq.extFlags,se.mSpOn);
  362.     ELSE
  363.     END;
  364.     IF config.radBoogie THEN INCL(serWriteReq.serFlags,se.radBoogie) END;
  365.     e.CopyMem(serWriteReq.ctlChar,serReadReq.ctlChar,SIZE(serReadReq^)-SIZE(e.IOStdReq));
  366.     serWriteReq.ioSer.command := se.setparams;
  367.     ioErr := e.DoIO(serWriteReq);
  368.     IF wasReading THEN
  369.       SendReadReq;
  370.     END;
  371.   END ConfigToSer;
  372.  
  373.  
  374.   PROCEDURE SerWriteString(txt: ARRAY OF CHAR); (* $CopyArrays- *)
  375.     CONST
  376.       setCtrlLines = e.nonstd + 7;
  377.       rtsF = 1;
  378.       dtrF = 2;
  379.     VAR
  380.       i,l: LONGINT;
  381.       s: ARRAY 8 OF CHAR;
  382.       ctrl: BOOLEAN;
  383.   BEGIN
  384.     ctrl := FALSE;
  385.     FOR i := 0 TO str.Length(txt)-1 DO
  386.       s[0] := txt[i]; s[1] := 0X;
  387.       IF ctrl THEN
  388.         CASE CAP(s[0]) OF
  389.           "R" : s[0] := "\r" |
  390.           "N" : s[0] := "\n" |
  391.           "E" : s[0] := "\e" |
  392.           "^","\\","~":
  393.         ELSE
  394.           s[0] := 0X
  395.         END;
  396.         ctrl := FALSE;
  397.       ELSE
  398.         CASE s[0] OF
  399.         | "\\": ctrl := TRUE; s[0] := 0X;
  400.         | "~" : d.Delay(d.ticksPerSecond DIV 2); s[0] := 0X;
  401.         | "^" : serWriteReq.ioSer.command := setCtrlLines;
  402.                 serWriteReq.ioSer.offset := dtrF;
  403.                 serWriteReq.ioSer.length := 0;
  404.                 IF e.DoIO(serWriteReq)#0 THEN
  405.                   INCL(hw.ciab.pra,hw.comDTR);
  406.                 END;
  407.                 d.Delay(d.ticksPerSecond DIV 8);
  408.                 serWriteReq.ioSer.command := setCtrlLines;
  409.                 serWriteReq.ioSer.offset := dtrF;
  410.                 serWriteReq.ioSer.length := dtrF;
  411.                 IF e.DoIO(serWriteReq)#0 THEN
  412.                   EXCL(hw.ciab.pra,hw.comDTR);
  413.                 END;
  414.                 s[0] := 0X;
  415.         ELSE
  416.         END;
  417.       END;
  418.       l := str.Length(s);
  419.       IF l>0 THEN
  420.         serWriteReq.ioSer.data := SYS.ADR(s);
  421.         serWriteReq.ioSer.length := l;
  422.         serWriteReq.ioSer.command := e.write;
  423.         ioErr := e.DoIO(serWriteReq);
  424.         IF config.duplex=halfduplex THEN
  425.           conWriteReq.length  := l;
  426.           conWriteReq.data    := SYS.ADR(s);
  427.           conWriteReq.command := e.write;
  428.           e.OldDoIO(conWriteReq);
  429.           Capture(SYS.ADR(s),l);
  430.         END;
  431.       END;
  432.     END;
  433.   END SerWriteString;
  434.  
  435.  
  436.   PROCEDURE MyRequest(title,textFormat,gadgetFormat: ARRAY OF CHAR;
  437.                       args: e.APTR): LONGINT; (* $CopyArrays- *)
  438.     VAR res: LONGINT;
  439.   BEGIN
  440.     BlockWindow;
  441.     res := rt.EZRequestTags(textFormat,gadgetFormat,NIL,args,rt.ezReqTitle,SYS.ADR(title),u.end);
  442.     UnBlockWindow;
  443.     RETURN res;
  444.   END MyRequest;
  445.  
  446.  
  447.   PROCEDURE Assert(cc: BOOLEAN; txt: ARRAY OF CHAR); (* $CopyArrays- *)
  448.   BEGIN
  449.     IF ~cc THEN
  450.       IF MyRequest("Information",txt,"Cancel",NIL)=0 THEN END;
  451.       HALT(d.fail);
  452.     END;
  453.   END Assert;
  454.  
  455.  
  456.   PROCEDURE RFProc; (* $EntryExitCode- *)
  457.   BEGIN
  458.     SYS.INLINE(016C0U,04E75U);
  459.   END RFProc;
  460.  
  461.  
  462.   PROCEDURE SplitLine(VAR line,first,rest: ARRAY OF CHAR);
  463.     VAR i,j,k,l: LONGINT;
  464.         quote,take,gotFirst: BOOLEAN;
  465.         ch,lastCh: CHAR;
  466.   BEGIN
  467.     quote := FALSE; gotFirst := FALSE;
  468.     i := 0; j := 0; k := 0; ch := 0X;
  469.     l := str.Length(line);
  470.     WHILE i<l DO
  471.       take := TRUE; lastCh := ch; ch := line[i];
  472.       CASE ch OF
  473.       | '"'      : quote := ~quote; IF ~quote OR (lastCh#'"') THEN take := FALSE END;
  474.       | " ","\t" : IF ~quote & ~gotFirst THEN
  475.                      gotFirst := TRUE;
  476.                      WHILE (i<l-1) & ((line[i+1]=" ")OR(line[i+1]="\t")) DO INC(i) END;
  477.                      take := FALSE;
  478.                    END;
  479.       ELSE
  480.       END;
  481.       IF take THEN
  482.         IF ~gotFirst THEN
  483.           IF j<LEN(first) THEN first[j] := ch; INC(j) END;
  484.         ELSE
  485.           IF k<LEN(rest)  THEN rest [k] := ch; INC(k) END;
  486.         END;
  487.       END;
  488.       INC(i);
  489.     END;
  490.     IF j<LEN(first) THEN first[j] := 0X END;
  491.     IF k<LEN(rest)  THEN rest [k] := 0X END;
  492.   END SplitLine;
  493.  
  494.  
  495.   PROCEDURE LoadConfig;
  496.     VAR file: fs.File;
  497.         string,keyword,valueStr: e.STRING;
  498.         value,dummy,i: LONGINT;
  499.   BEGIN
  500.     config.device        := "serial.device";
  501.     config.unit          := 0;
  502.     config.initString    := "ATZ\\r~~";
  503.     config.hangupString  := "^~~~+++~~~ATH0\\r";
  504.     config.rBufLen       := 8192;
  505.     config.baud          := 2400;
  506.     config.breakTime     := 250000;
  507.     config.bitsPerChar   := 8;
  508.     config.stopBits      := 1;
  509.     config.parity        := none;
  510.     config.handShaking   := ctsrts;
  511.     config.radBoogie     := FALSE;
  512.     config.duplex        := fullduplex;
  513.     config.keyMap        := "";
  514.     config.font          := "";
  515.     config.protocol      := "";
  516.     config.downloadDir   := "";
  517.     config.uploadDir     := "";
  518.     config.pasteDir      := "";
  519.     config.capture       := "T:Capture_";
  520.     config.screenDepth   := 2;
  521.     config.time4connect  := 0;
  522.     config.pasteDelay    := 10;
  523.     config.priority      := 0;
  524.  
  525.     IF args.config # NIL THEN
  526.       COPY(args.config^,string);
  527.     ELSE
  528.       string := "Termite.config";
  529.       IF ~fs.Exists(string) THEN
  530.         string := "PROGDIR:Termite.config";
  531.         IF resident OR ~fs.Exists(string) THEN
  532.           string := "ENV:Termite.config";
  533.           IF ~fs.Exists(string) THEN
  534.             string := "s:Termite.config";
  535.             IF ~fs.Exists(string) THEN
  536.               string := ""
  537.             END;
  538.           END;
  539.         END;
  540.       END;
  541.     END;
  542.     IF fs.Open(file,string,FALSE) THEN
  543.       WHILE fs.ReadString(file,string) DO
  544.         IF RemSpaces(string) THEN
  545.           SplitLine(string,keyword,valueStr);
  546.           str.Upper(keyword);
  547.           value := StringToInt(valueStr,10);
  548.  
  549.           IF    keyword = "DEVICE"      THEN config.device := valueStr
  550.           ELSIF keyword = "UNIT"        THEN config.unit := SHORT(value)
  551.           ELSIF keyword = "HANDSHAKING" THEN str.Upper(valueStr); IF valueStr="XONXOFF" THEN config.handShaking:=xonxoff ELSIF valueStr="7WIRE" THEN config.handShaking:=ctsrts ELSE config.handShaking:=none END;
  552.           ELSIF keyword = "BAUDRATE"    THEN config.baud         := value
  553.           ELSIF keyword = "BREAKTIME"   THEN config.breakTime    := value
  554.           ELSIF keyword = "SERIALBUFFER"THEN config.rBufLen      := value DIV 512 * 512;
  555.           ELSIF keyword = "PARITY"      THEN str.Upper(valueStr); IF    valueStr="EVEN" THEN config.parity:=even  ELSIF valueStr="ODD"THEN config.parity:=odd ELSIF valueStr="MARK" THEN config.parity:=mark
  556.                                                                   ELSIF valueStr="SPACE"THEN config.parity:=space ELSE config.parity:=none END;
  557.           ELSIF keyword = "DUPLEX"      THEN str.Upper(valueStr); IF valueStr="FULL" THEN config.duplex:=fullduplex ELSE config.duplex:=halfduplex END;
  558.           ELSIF keyword = "RADBOOGIE"   THEN str.Upper(valueStr); config.radBoogie := valueStr#"FALSE"
  559.           ELSIF keyword = "TIMEFORCONNECT" THEN config.time4connect := value
  560.           ELSIF keyword = "PASTEDELAY"  THEN config.pasteDelay   := value
  561.           ELSIF keyword = "INITSTRING"  THEN config.initString   := valueStr
  562.           ELSIF keyword = "HANGUPSTRING"THEN config.hangupString := valueStr
  563.           ELSIF keyword = "STOPBITS"    THEN config.stopBits     := SHORT(SHORT(value))
  564.           ELSIF keyword = "BITSPERCHAR" THEN config.bitsPerChar  := SHORT(SHORT(value))
  565.           ELSIF keyword = "KEYMAP"      THEN config.keyMap       := valueStr
  566.           ELSIF keyword = "SCREENDEPTH" THEN config.screenDepth  := SHORT(value)
  567.           ELSIF keyword = "PRIORITY"    THEN config.priority     := SHORT(SHORT(value))
  568.           ELSIF keyword = "PROTOCOL"    THEN config.protocol     := valueStr
  569.           ELSIF keyword = "CAPTURE"     THEN config.capture      := valueStr
  570.           ELSIF keyword = "UPLOADDIR"   THEN config.uploadDir    := valueStr
  571.           ELSIF keyword = "DOWNLOADDIR" THEN config.downloadDir  := valueStr
  572.           ELSIF keyword = "PASTEDIR"    THEN config.pasteDir     := valueStr
  573.           ELSIF(keyword = "FONT") & (config.font="") THEN
  574.             config.font := valueStr;
  575.             i := d.SplitName(valueStr,"/",string,0,LEN(string));
  576.             IF (i # -1) & (string # "") THEN
  577.               str.Append(string,".font");
  578.               NEW(attr);
  579.               NEW(attr.name);
  580.               COPY(string,attr.name^);
  581.               e.CopyMem(valueStr[i],string,LEN(string));
  582.               IF string # "" THEN
  583.                 attr.ySize := SHORT(StringToInt(string,10));
  584.                 IF attr.ySize <  5 THEN attr.ySize :=  5 END;
  585.                 IF attr.ySize > 50 THEN attr.ySize := 50 END;
  586.                 font := df.OpenDiskFont(attr^);
  587.                 IF font # NIL THEN
  588.                   attr.ySize := font.ySize;
  589.                 ELSE
  590.                   attr := NIL;
  591.                 END;
  592.               ELSE
  593.                 attr := NIL;
  594.               END;
  595.             END;
  596.           ELSIF keyword = "PALETTE"     THEN
  597.             colorCnt := 0;
  598.             WHILE str.Length(valueStr)>0 DO
  599.               i := 0;
  600.               WHILE (valueStr[0]#",") & (valueStr[0]#0X) DO
  601.                 IF i<LEN(string) THEN
  602.                   string[i] := valueStr[0]; INC(i);
  603.                 END;
  604.                 str.Delete(valueStr,0,1);
  605.               END;
  606.               IF i<LEN(string) THEN string[i] := 0X END;
  607.               IF valueStr[0]="," THEN str.Delete(valueStr,0,1) END;
  608.               IF colorCnt<LEN(colorMap) THEN
  609.                 colorMap[colorCnt] := SHORT(StringToInt(string,16));
  610.                 INC(colorCnt)
  611.               END;
  612.             END;
  613.           END;
  614.         END;
  615.       END;
  616.       IF fs.Close(file) THEN END;
  617.     END;
  618.     IF config.screenDepth<  1 THEN config.screenDepth:=  1 ELSIF config.screenDepth>      4 THEN config.screenDepth:=      4 END;
  619.     IF config.breakTime  <  1 THEN config.breakTime  :=  1 ELSIF config.breakTime  >5000000 THEN config.breakTime  :=5000000 END;
  620.     IF config.rBufLen    <512 THEN config.rBufLen    :=512 ELSIF config.rBufLen    >  65536 THEN config.rBufLen    :=  65536 END;
  621.     IF config.bitsPerChar<  7 THEN config.bitsPerChar:=  7 ELSIF config.bitsPerChar>      8 THEN config.bitsPerChar:=      8 END;
  622.     IF config.stopBits   <  1 THEN config.stopBits   :=  1 ELSIF config.stopBits   >      2 THEN config.stopBits   :=      2 END;
  623.     IF config.baud       <112 THEN config.baud       :=112 ELSIF config.baud       > 115200 THEN config.baud       := 115200 END;
  624.     IF config.time4connect< 0 THEN config.time4connect:= 0 ELSIF config.time4connect> 10000 THEN config.time4connect:= 10000 END;
  625.     IF config.pasteDelay <  0 THEN config.pasteDelay :=  0 ELSIF config.pasteDelay >   1000 THEN config.pasteDelay :=   1000 END;
  626.   END LoadConfig;
  627.  
  628.  
  629.   PROCEDURE PutText(win: I.WindowPtr; x,y: INTEGER; txt: ARRAY OF CHAR; n: LONGINT); (* $CopyArrays- *)
  630.     VAR
  631.       l: LONGINT;
  632.       rp: g.RastPortPtr;
  633.       text: ARRAY 50 OF CHAR;
  634.   BEGIN
  635.     rp := win.rPort;
  636.     g.Move(rp,win.borderLeft+(x-1)*rp.txWidth,win.borderTop+(y-1)*rp.txHeight+rp.txBaseline);
  637.     IF n<=0 THEN
  638.       g.Text(rp,txt,str.Length(txt));
  639.     ELSE
  640.       text := "                                                  ";
  641.       l := str.Length(txt);
  642.       IF l>50 THEN l := 50 END;
  643.       IF l>0 THEN e.CopyMem(txt,text,l) END;
  644.       IF n>50 THEN n := 50 END;
  645.       g.Text(rp,text,n);
  646.     END;
  647.   END PutText;
  648.  
  649.  
  650.   PROCEDURE DrawBox(rp: g.RastPortPtr; left,top,width,height: INTEGER);
  651.   BEGIN
  652.     IF (width > 0) & (height > 0) THEN
  653.       g.RectFill(rp,left,top,left+width-1,top+height-1);
  654.     END;
  655.   END DrawBox;
  656.  
  657.  
  658.   PROCEDURE OpenTransferWindow(title: ARRAY OF CHAR): BOOLEAN; (* $CopyArrays- *)
  659.     VAR
  660.       rp: g.RastPortPtr;
  661.       box: I.IBox;
  662.       try: INTEGER;
  663.       oldPt: e.APTR;
  664.       oldPtSz: SHORTINT;
  665.   BEGIN
  666.     IF transferWin = NIL THEN
  667.  
  668.       box.width  := scr.rastPort.txWidth  * 63 + 10;
  669.       box.height := scr.rastPort.txHeight * 16 + 16;
  670.  
  671.       try := 0;
  672.       LOOP
  673.         INC(try);
  674.  
  675.         box.top  := (scr.height-(box.height+scr.barHeight)) DIV 2;
  676.         box.left := (scr.width -box.width)  DIV 2;
  677.  
  678.         transferWin := I.OpenWindowTagsA(NIL,
  679.                             I.waTitle,       SYS.ADR(title),
  680.                             I.waLeft,        box.left,
  681.                             I.waTop,         box.top,
  682.                             I.waInnerHeight, box.height,
  683.                             I.waInnerWidth,  box.width,
  684.                             I.waAutoAdjust,  I.LFALSE,
  685.                             I.waIDCMP,       LONGSET{I.closeWindow},
  686.                             I.waFlags,       LONGSET{I.activate,I.noCareRefresh,I.windowDrag,I.windowDepth,I.windowClose,I.rmbTrap},
  687.                             I.waCustomScreen,scr,
  688.                             u.done);
  689.         IF transferWin#NIL THEN
  690.           IF try=2 THEN g.SetFont(transferWin.rPort,topaz80) END;
  691.           EXIT
  692.         END;
  693.  
  694.         IF (try=2) OR (topaz80=NIL) THEN RETURN FALSE END;
  695.  
  696.         box.width  := 8 * 63 + 10;
  697.         box.height := 8 * 16 + 16;
  698.       END;
  699.  
  700.       BlockWindow;
  701.   
  702.       rp := transferWin.rPort;
  703.  
  704.       g.SetDrMd(rp,g.jam2);
  705.       g.SetAPen(rp,1);
  706.   
  707.       PutText(transferWin, 2,2,"Protocol:",0);
  708.       PutText(transferWin, 2,3,"File Name:",0);
  709.   
  710.       PutText(transferWin, 2,5,"Status:",0);
  711.       PutText(transferWin, 2,6,"Error Msg:",0);
  712.   
  713.       PutText(transferWin, 2, 8,"File Size:",0);      PutText(transferWin,32, 8,"Timeouts:",0);
  714.       PutText(transferWin, 2, 9,"Bytes transf.:",0);  PutText(transferWin,32, 9,"Errors:",0);
  715.       PutText(transferWin, 2,10,"Blocks transf.:",0); PutText(transferWin,32,10,"Char. Delay:",0);
  716.       PutText(transferWin, 2,11,"Block Size:",0);     PutText(transferWin,32,11,"Packet Delay:",0);
  717.       PutText(transferWin, 2,12,"Block Check:",0);    PutText(transferWin,32,12,"Expected Time:",0);
  718.       PutText(transferWin, 2,13,"Chars/Sec:",0);      PutText(transferWin,32,13,"Elapsed Time:",0);
  719.   
  720.       PutText(transferWin, 25,15,"Data transferred",0);
  721.   
  722.       bbox.width  := transferWin.width * 3 DIV 4;
  723.       bbox.height := rp.txHeight+4;
  724.       bbox.left   := (transferWin.width-bbox.width) DIV 2;
  725.       bbox.top    := transferWin.borderTop+(16-1)*rp.txHeight+4;
  726.  
  727.       gt.DrawBevelBox(rp,bbox.left-2,bbox.top-1,bbox.width+4,bbox.height+2, gt.visualInfo,vi,gt.bbRecessed,I.LTRUE,u.end);
  728.  
  729.       g.SetDrMd(rp,g.jam1);
  730.       afpt[0] := 05555U; afpt[1] := 0AAAAU;
  731.       oldPt := rp.areaPtrn; oldPtSz := rp.areaPtSz;
  732.       g.SetAfPt(rp,SYS.ADR(afpt),1);
  733.       DrawBox(rp,bbox.left,bbox.top,bbox.width,bbox.height);
  734.       g.SetAfPt(rp,oldPt,oldPtSz);
  735.       g.SetDrMd(rp,g.jam2);
  736.     END;
  737.     RETURN TRUE;
  738.   END OpenTransferWindow;
  739.  
  740.  
  741.   PROCEDURE CloseTransferWindow;
  742.   BEGIN
  743.     IF transferWin # NIL THEN
  744.       d.Delay(d.ticksPerSecond);
  745.       UnBlockWindow;
  746.       I.CloseWindow(transferWin);
  747.       transferWin := NIL;
  748.     END;
  749.   END CloseTransferWindow;
  750.  
  751.  
  752.   PROCEDURE Transfer(upload: BOOLEAN);
  753.     VAR ok: BOOLEAN;
  754.   BEGIN
  755.     IF XPR.base=NIL THEN RETURN END;
  756.     IF upload THEN ok := OpenTransferWindow("Upload")
  757.               ELSE ok := OpenTransferWindow("Download") END;
  758.     IF ok THEN
  759.       AbortReadReq;
  760.       IF upload THEN ok := XPR.XProtocolSend(xprio^);
  761.                 ELSE ok := XPR.XProtocolReceive(xprio^); END;
  762.       SendReadReq;
  763.       CloseTransferWindow;
  764.     END;
  765.   END Transfer;
  766.  
  767.  
  768.   PROCEDURE CloseProtocol;
  769.     VAR item: I.MenuItemPtr;
  770.   BEGIN
  771.     IF XPR.base # NIL THEN
  772.       XPR.XProtocolCleanup(xprio^);
  773.       e.CloseLibrary(XPR.base);
  774.       XPR.base := NIL;
  775.       xprio.data := NIL;
  776.       xprio.filename := NIL;
  777.       config.protocol := "";
  778.       IF menu#NIL THEN
  779.         IF (win#NIL) & (win.menuStrip#NIL) THEN
  780.           I.OffMenu(win,I.UIntToLong(I.FullMenuNum(5,4,I.noSub)));
  781.         ELSE
  782.           item := I.ItemAddress(menu^,I.UIntToLong(I.FullMenuNum(5,4,I.noSub)));
  783.           EXCL(item.flags,I.itemEnabled);
  784.         END;
  785.       END;
  786.     END;
  787.   END CloseProtocol;
  788.  
  789.  
  790.   CONST
  791.     cantLoadProtocol  = 1;
  792.     cantSetupProtocol = 2;
  793.  
  794.  
  795.   PROCEDURE OpenProtocol(name: ARRAY OF CHAR): INTEGER; (* $CopyArrays- *)
  796.     VAR libName: ARRAY 80 OF CHAR;
  797.         xprname: ARRAY 80 OF CHAR;
  798.         base: e.LibraryPtr;
  799.         item: I.MenuItemPtr;
  800.   BEGIN
  801.     COPY(name,xprname);
  802.     str.Insert(xprname,0,"xpr");
  803.     COPY(xprname,libName);
  804.     str.Append(libName,".library");
  805.     base := e.OpenLibrary(libName,0);
  806.     IF base # NIL THEN
  807.       CloseProtocol;
  808.       XPR.base := base;
  809.       IF d.GetVar(xprname,protocolOpts,LEN(protocolOpts),LONGSET{}) > 0 THEN
  810.         xprio.filename := SYS.ADR(protocolOpts);
  811.       END;
  812.       xprFlags := XPR.XProtocolSetup(xprio^);
  813.       (* $IF debug *)
  814.       d.PrintF("xprflags=%lx\n",SYS.VAL(LONGINT,xprFlags));
  815.       (* $END *)
  816.       IF ~(XPR.success IN xprFlags) THEN
  817.         CloseProtocol;
  818.         RETURN cantSetupProtocol;
  819.       ELSE
  820.         IF menu#NIL THEN
  821.           IF (win#NIL) & (win.menuStrip#NIL) THEN
  822.             I.OnMenu(win,I.UIntToLong(I.FullMenuNum(5,4,I.noSub)));
  823.           ELSE
  824.             item := I.ItemAddress(menu^,I.UIntToLong(I.FullMenuNum(5,4,I.noSub)));
  825.             INCL(item.flags,I.itemEnabled);
  826.           END;
  827.         END;
  828.       END;
  829.     ELSE
  830.       RETURN cantLoadProtocol
  831.     END;
  832.     RETURN 0
  833.   END OpenProtocol;
  834.  
  835.  
  836. (*------------------- XPR Callback Functions ----------------------*)
  837.  
  838.   (* $StackChk- *)
  839.  
  840.   (* $SaveRegs+ *)
  841.  
  842.   PROCEDURE fopen(filename{8}: e.STRPTR; accessmode{9}: e.STRPTR): d.FileHandlePtr;
  843.     VAR file: d.FileHandlePtr;
  844.         ok: BOOLEAN;
  845.   BEGIN
  846.     ol.SetA5;
  847.     (* $IF debug *)
  848.     d.PrintF("fopen %s\n",filename);
  849.     (* $END *)
  850.     file := NIL;
  851.     CASE CAP(accessmode^[0]) OF
  852.       "R": file := d.Open(filename^,d.oldFile);
  853.     | "W": file := d.Open(filename^,d.newFile);
  854.     | "A": file := d.Open(filename^,d.oldFile);
  855.            IF file#NIL THEN
  856.              IF d.Seek(file,0,d.end)=0 THEN END;
  857.            ELSE
  858.              file := d.Open(filename^,d.newFile);
  859.            END;
  860.     ELSE
  861.     END;
  862.     RETURN file;
  863.   END fopen;
  864.  
  865.  
  866.   (* $SaveRegs+ *)
  867.  
  868.   PROCEDURE fclose(fileptr{8}: d.FileHandlePtr): LONGINT;
  869.   BEGIN
  870.     ol.SetA5;
  871.     (* $IF debug *)
  872.     d.PrintF("fclose\n");
  873.     (* $END *)
  874.     d.OldClose(fileptr);
  875.     RETURN 0;
  876.   END fclose;
  877.  
  878.  
  879.   (* $SaveRegs+ *)
  880.  
  881.   PROCEDURE fread(buffer{8}: e.STRPTR; size{0},count{1}: LONGINT; fileptr{9}: d.FileHandlePtr): LONGINT;
  882.     VAR n,siz,cnt: LONGINT;
  883.   BEGIN
  884.     siz := size;
  885.     cnt := count;
  886.     ol.SetA5;
  887.     (* $IF debug *)
  888.     d.PrintF("fread %ld,%ld\n",siz,cnt);
  889.     (* $END *)
  890.     IF (siz>0) & (cnt>0) THEN
  891.       n := d.FRead(fileptr,buffer^,siz,cnt);
  892.       IF n > 0 THEN
  893.         RETURN n
  894.       END;
  895.     END;
  896.     RETURN 0;
  897.   END fread;
  898.  
  899.  
  900.   (* $SaveRegs+ *)
  901.  
  902.   PROCEDURE fwrite(buffer{8}: e.STRPTR; size{0},count{1}: LONGINT; fileptr{9}: d.FileHandlePtr): LONGINT;
  903.     VAR n,siz,cnt: LONGINT;
  904.   BEGIN
  905.     siz := size;
  906.     cnt := count;
  907.     ol.SetA5;
  908.     (* $IF debug *)
  909.     d.PrintF("fwrite %ld,%ld\n",siz,cnt);
  910.     (* $END *)
  911.     IF (siz>0) & (cnt>0) THEN
  912.       n := d.FWrite(fileptr,buffer^,siz,cnt);
  913.       IF n > 0 THEN
  914.         RETURN n
  915.       END;
  916.     END;
  917.     RETURN 0;
  918.   END fwrite;
  919.  
  920.  
  921.   (* $SaveRegs+ *)
  922.  
  923.   PROCEDURE finfo(filename{8}: e.STRPTR; typeofinfo{0}: LONGINT): LONGINT;
  924.     VAR infotype: LONGINT;
  925.         lock: d.FileLockPtr;
  926.         fib: d.FileInfoBlockPtr;
  927.         res: LONGINT;
  928.   BEGIN
  929.     infotype := typeofinfo;
  930.     ol.SetA5;
  931.     (* $IF debug *)
  932.     d.PrintF("finfo\n");
  933.     (* $END *)
  934.     res := 0;
  935.     CASE infotype OF
  936.       1: lock := d.Lock(filename^,d.sharedLock);
  937.          IF lock#NIL THEN
  938.            fib := d.AllocDosObjectTags(d.fib,u.done);
  939.            IF fib # NIL THEN
  940.              IF d.Examine(lock,fib^) THEN
  941.                res := fib.size
  942.              END;
  943.              d.FreeDosObject(d.fib,fib);
  944.            END;
  945.            d.UnLock(lock);
  946.          END;
  947.     | 2: res := 1
  948.     ELSE
  949.     END;
  950.     RETURN res
  951.   END finfo;
  952.  
  953.  
  954.   (* $SaveRegs+ *)
  955.  
  956.   PROCEDURE fseek(fileptr{8}: d.FileHandlePtr; offset{0},origin{1}: LONGINT): LONGINT;
  957.     VAR
  958.       offs,orgn: LONGINT;
  959.   BEGIN
  960.     offs := offset;
  961.     orgn := origin;
  962.     ol.SetA5;
  963.     (* $IF debug *)
  964.     d.PrintF("fseek\n");
  965.     (* $END *)
  966.     IF d.Seek(fileptr,offs,orgn-1)=-1 THEN RETURN -1
  967.                                       ELSE RETURN  0 END;
  968.   END fseek;
  969.  
  970.  
  971.   (* $SaveRegs+ *)
  972.  
  973.   PROCEDURE unlink(filename{8}: e.STRPTR): LONGINT;
  974.   BEGIN
  975.     ol.SetA5;
  976.     (* $IF debug *)
  977.     d.PrintF("unlink\n");
  978.     (* $END *)
  979.     IF d.DeleteFile(filename^) THEN RETURN  0
  980.                                ELSE RETURN -1 END;
  981.   END unlink;
  982.  
  983.  
  984.   (* $SaveRegs+ *)
  985.  
  986.   PROCEDURE chkabort(): LONGINT;
  987.     VAR msg: I.IntuiMessagePtr;
  988.         res: LONGINT;
  989.   BEGIN
  990.     ol.SetA5;
  991.     (* $IF debug *)
  992.     d.PrintF("chkabort\n");
  993.     (* $END *)
  994.     IF transferWin=NIL THEN RETURN 0 END;
  995.     res := 0;
  996.     LOOP
  997.       msg := e.GetMsg(transferWin.userPort);
  998.       IF msg=NIL THEN EXIT END;
  999.       IF I.closeWindow IN msg.class THEN
  1000.         IF (res=0) & (MyRequest("Request","Abort Transfer?","Abort|Cancel",NIL)#0) THEN
  1001.           res := -1;
  1002.         END;
  1003.       END;
  1004.       e.ReplyMsg(msg);
  1005.     END;
  1006.     RETURN res;
  1007.   END chkabort;
  1008.  
  1009.  
  1010.   (* $SaveRegs+ *)
  1011.  
  1012.   PROCEDURE sread(buffer{8}: e.STRPTR; size{0},timeout{1}: LONGINT): LONGINT;
  1013.     VAR siz,tmout: LONGINT;
  1014.         sigRec: LONGSET;
  1015.         sigTimer: SHORTINT;
  1016.   BEGIN
  1017.     siz := size;
  1018.     tmout := timeout;
  1019.     ol.SetA5;
  1020.     (* $IF debug *)
  1021.     d.PrintF("sread\n");
  1022.     (* $END *)
  1023.     IF chkabort()#0 THEN RETURN -1 END;
  1024.     IF siz <= 0 THEN RETURN 0 END;
  1025.     serWriteReq.ioSer.command := se.query;
  1026.     e.OldDoIO(serWriteReq);
  1027.     IF tmout < 1 THEN
  1028.       IF serWriteReq.ioSer.actual > 0 THEN
  1029.         serReadReq.ioSer.length  := Min(serWriteReq.ioSer.actual,siz);
  1030.         serReadReq.ioSer.command := e.read;
  1031.         serReadReq.ioSer.data    := buffer;
  1032.         IF e.DoIO(serReadReq)=0 THEN RETURN serReadReq.ioSer.actual END;
  1033.       END;
  1034.     ELSE
  1035.       IF serWriteReq.ioSer.actual < siz THEN
  1036.         timeReq.node.command := ti.addRequest;
  1037.         IF tmout < 1000000 THEN
  1038.           timeReq.time.secs  := 0;
  1039.           timeReq.time.micro := tmout;
  1040.         ELSE
  1041.           timeReq.time.secs  := tmout DIV 1000000;
  1042.           timeReq.time.micro := tmout MOD 1000000;
  1043.         END;
  1044.         serReadReq.ioSer.command := e.read;
  1045.         serReadReq.ioSer.data    := buffer;
  1046.         serReadReq.ioSer.length  := siz;
  1047.         sigTimer := timeReq.node.message.replyPort.sigBit;
  1048.         SYS.SETREG(0,e.SetSignal(LONGSET{},LONGSET{serReadPort.sigBit,sigTimer}));
  1049.         e.SendIO(serReadReq);
  1050.         e.SendIO(timeReq);
  1051.         LOOP
  1052.           sigRec := e.Wait(LONGSET{serReadPort.sigBit,sigTimer});
  1053.           IF sigTimer IN sigRec THEN
  1054.             e.AbortIO(serReadReq);
  1055.             e.OldWaitIO(serReadReq);
  1056.             e.OldWaitIO(timeReq);
  1057.             IF serReadReq.ioSer.actual=0 THEN
  1058.               serWriteReq.ioSer.command := se.query;
  1059.               e.OldDoIO(serWriteReq);
  1060.               IF serWriteReq.ioSer.actual > 0 THEN
  1061.                 serReadReq.ioSer.length  := Min(serWriteReq.ioSer.actual,siz);
  1062.                 serReadReq.ioSer.command := e.read;
  1063.                 serReadReq.ioSer.data    := buffer;
  1064.                 IF e.DoIO(serReadReq)=0 THEN RETURN serReadReq.ioSer.actual
  1065.                                      ELSE RETURN 0 END;
  1066.               ELSE
  1067.                 RETURN 0
  1068.               END;
  1069.             ELSE
  1070.               RETURN serReadReq.ioSer.actual
  1071.             END;
  1072.           END;
  1073.           IF serReadPort.sigBit IN sigRec THEN
  1074.             e.AbortIO(timeReq);
  1075.             e.OldWaitIO(timeReq);
  1076.             e.OldWaitIO(serReadReq);
  1077.             IF serReadReq.ioSer.error=0 THEN RETURN serReadReq.ioSer.actual
  1078.                                      ELSE RETURN 0 END;
  1079.           END;
  1080.         END; (* LOOP *)
  1081.       ELSE
  1082.         serReadReq.ioSer.command := e.read;
  1083.         serReadReq.ioSer.data    := buffer;
  1084.         serReadReq.ioSer.length  := siz;
  1085.         IF e.DoIO(serReadReq)=0 THEN RETURN siz END;
  1086.       END;
  1087.     END;
  1088.     RETURN 0;
  1089.   END sread;
  1090.  
  1091.  
  1092.   (* $SaveRegs+ *)
  1093.  
  1094.   PROCEDURE swrite(buffer{8}: e.STRPTR; size{0}: LONGINT): LONGINT;
  1095.     VAR siz: LONGINT;
  1096.   BEGIN
  1097.     siz := size;
  1098.     ol.SetA5;
  1099.     (* $IF debug *)
  1100.     d.PrintF("swrite\n");
  1101.     (* $END *)
  1102.     serWriteReq.ioSer.data := buffer;
  1103.     serWriteReq.ioSer.length := siz;
  1104.     serWriteReq.ioSer.command := e.write;
  1105.     RETURN e.DoIO(serWriteReq);
  1106.   END swrite;
  1107.  
  1108.  
  1109.   (* $SaveRegs+ *)
  1110.  
  1111.   PROCEDURE sflush(): LONGINT;
  1112.   BEGIN
  1113.     ol.SetA5;
  1114.     (* $IF debug *)
  1115.     d.PrintF("sflush\n");
  1116.     (* $END *)
  1117.     serWriteReq.ioSer.command := e.clear;
  1118.     RETURN e.DoIO(serWriteReq);
  1119.   END sflush;
  1120.  
  1121.  
  1122.   (* $SaveRegs+ *)
  1123.  
  1124.   PROCEDURE update(us{8}: XPR.UpdatePtr): LONGINT;
  1125.     VAR mask: LONGSET;
  1126.         p,w,len: INTEGER;
  1127.         txt: ARRAY 50 OF CHAR;
  1128.         rp: g.RastPortPtr;
  1129.   BEGIN
  1130.     ol.SetA5;
  1131.     (* $IF debug *)
  1132.     d.PrintF("update\n");
  1133.     (* $END *)
  1134.     IF transferWin=NIL THEN
  1135.       IF ~OpenTransferWindow("Auto Transfer") THEN RETURN 0 END;
  1136.     END;
  1137.     rp := transferWin.rPort;
  1138.     g.SetAPen(transferWin.rPort,2);
  1139.     mask := us.updatemask;
  1140.     IF (XPR.protocol    IN mask)&(us.protocol   #NIL)THEN PutText(transferWin, 2+11,2,us.protocol^,50)    END;
  1141.     IF (XPR.filename    IN mask)&(us.filename   #NIL)THEN PutText(transferWin, 2+11,3,us.filename^,50)    END;
  1142.     IF (XPR.blockcheck  IN mask)&(us.blockcheck #NIL)THEN PutText(transferWin, 2+16,12,us.blockcheck^,14) END;
  1143.     IF (XPR.expecttime  IN mask)&(us.expecttime #NIL)THEN PutText(transferWin,32+15,12,us.expecttime^,14) END;
  1144.     IF (XPR.elapsedtime IN mask)&(us.elapsedtime#NIL)THEN PutText(transferWin,32+15,13,us.elapsedtime^,14)END;
  1145.     IF (XPR.msg         IN mask)&(us.msg        #NIL)THEN PutText(transferWin, 2+11,5,us.msg^,50);        END;
  1146.     IF (XPR.errormsg    IN mask)&(us.errormsg   #NIL)THEN PutText(transferWin, 2+11,6,us.errormsg^,50);   END;
  1147.     IF (XPR.filesize    IN mask)&(us.filesize   #-1) THEN e.RawDoFmt("%ld",SYS.ADR(us.filesize),RFProc,SYS.ADR(txt));    PutText(transferWin, 2+16, 8,txt,14) END;
  1148.     IF (XPR.blocks      IN mask)&(us.blocks     #-1) THEN e.RawDoFmt("%ld",SYS.ADR(us.blocks),RFProc,SYS.ADR(txt));      PutText(transferWin, 2+16,10,txt,14) END;
  1149.     IF (XPR.blocksize   IN mask)&(us.blocksize  #-1) THEN e.RawDoFmt("%ld",SYS.ADR(us.blocksize),RFProc,SYS.ADR(txt));   PutText(transferWin, 2+16,11,txt,14) END;
  1150.     IF (XPR.bytes       IN mask)&(us.bytes      #-1) THEN e.RawDoFmt("%ld",SYS.ADR(us.bytes),RFProc,SYS.ADR(txt));       PutText(transferWin, 2+16, 9,txt,14) END;
  1151.     IF (XPR.errors      IN mask)&(us.errors     #-1) THEN e.RawDoFmt("%ld",SYS.ADR(us.errors),RFProc,SYS.ADR(txt));      PutText(transferWin,32+15, 9,txt,14) END;
  1152.     IF (XPR.timeouts    IN mask)&(us.timeouts   #-1) THEN e.RawDoFmt("%ld",SYS.ADR(us.timeouts),RFProc,SYS.ADR(txt));    PutText(transferWin,32+15, 8,txt,14) END;
  1153.     IF (XPR.packetdelay IN mask)&(us.packetdelay#-1) THEN e.RawDoFmt("%ld",SYS.ADR(us.packetdelay),RFProc,SYS.ADR(txt)); PutText(transferWin,32+15,11,txt,14) END;
  1154.     IF (XPR.chardelay   IN mask)&(us.chardelay  #-1) THEN e.RawDoFmt("%ld",SYS.ADR(us.chardelay),RFProc,SYS.ADR(txt));   PutText(transferWin,32+15,10,txt,14) END;
  1155.     IF (XPR.datarate    IN mask)&(us.datarate   #-1) THEN e.RawDoFmt("%ld",SYS.ADR(us.datarate),RFProc,SYS.ADR(txt));    PutText(transferWin, 2+16,13,txt,14) END;
  1156.     IF (XPR.bytes       IN mask)&(us.bytes#-1) & (us.filesize>0) & (us.bytes<20000000) THEN
  1157.       p := SHORT((us.bytes * 100) DIV us.filesize);
  1158.       IF p<0 THEN p := 0 ELSIF p>100 THEN p := 100 END;
  1159.       w := SHORT((bbox.width * LONG(p)) DIV 100);
  1160.       g.SetAPen(rp,3); DrawBox(rp,bbox.left,  bbox.top,w           ,bbox.height);
  1161.       g.SetAPen(rp,0); DrawBox(rp,bbox.left+w,bbox.top,bbox.width-w,bbox.height);
  1162.       e.RawDoFmt("%d%%",SYS.ADR(p),RFProc,SYS.ADR(txt));
  1163.       g.SetAPen(rp,2);
  1164.       g.SetDrMd(rp,g.jam1);
  1165.       len := SHORT(str.Length(txt));
  1166.       g.Move(rp,bbox.left+(bbox.width-len*rp.txWidth) DIV 2,bbox.top+rp.txBaseline+2);
  1167.       g.Text(rp,txt,len);
  1168.       g.SetDrMd(rp,g.jam2);
  1169.     END;
  1170.     RETURN 0
  1171.   END update;
  1172.  
  1173.  
  1174.   (* $SaveRegs+ *)
  1175.  
  1176.   PROCEDURE setserial(newstatus{0}: LONGINT): LONGINT;
  1177.     TYPE
  1178.       Status=STRUCT byte3:SHORTINT; byte2:SHORTINT; byte1:SHORTSET; byte0:SHORTSET END;
  1179.     VAR
  1180.       newstat, oldstat: Status;
  1181.       i: SHORTINT; found: BOOLEAN;
  1182.   BEGIN
  1183.     newstat := SYS.VAL(Status,newstatus);
  1184.     ol.SetA5;
  1185.     (* $IF debug *)
  1186.     d.PrintF("setserial\n");
  1187.     (* $END *)
  1188.     serWriteReq.ioSer.command := se.query;
  1189.     e.OldDoIO(serWriteReq);
  1190.     oldstat.byte0 := serWriteReq.serFlags;
  1191.     oldstat.byte1 := SHORTSET{};
  1192.     IF se.mSpOn IN serWriteReq.extFlags THEN INCL(oldstat.byte1,0) END;
  1193.     IF se.mark  IN serWriteReq.extFlags THEN INCL(oldstat.byte1,1) END;
  1194.     IF serWriteReq.stopBits = 2         THEN INCL(oldstat.byte1,2) END;
  1195.     IF serWriteReq.readLen  = 7         THEN INCL(oldstat.byte1,3) END;
  1196.     IF serWriteReq.writeLen = 7         THEN INCL(oldstat.byte1,4) END;
  1197.     i := 0; found := FALSE;
  1198.     WHILE (i < LEN(baudRates)) & ~found DO
  1199.       IF serWriteReq.baud = baudRates[i] THEN
  1200.         oldstat.byte2 := i;
  1201.         found := TRUE
  1202.       END;
  1203.       INC(i)
  1204.     END;
  1205.     IF ~found THEN RETURN -1 END;
  1206.     oldstat.byte3 := 0;
  1207.     IF SYS.VAL(LONGINT,newstat) # -1 THEN
  1208.       IF (newstat.byte2 >= 0) & (newstat.byte2 < LEN(baudRates)) THEN
  1209.         serWriteReq.baud := baudRates[newstat.byte2];
  1210.       ELSE RETURN -1
  1211.       END;
  1212.       serWriteReq.serFlags := newstat.byte0;
  1213.       serWriteReq.extFlags := LONGSET{};
  1214.       IF 0 IN newstat.byte1 THEN INCL(serWriteReq.extFlags,se.mSpOn) END;
  1215.       IF 1 IN newstat.byte1 THEN INCL(serWriteReq.extFlags,se.mark) END;
  1216.       IF 2 IN newstat.byte1 THEN serWriteReq.stopBits := 2 ELSE serWriteReq.stopBits := 1 END;
  1217.       IF 3 IN newstat.byte1 THEN serWriteReq.readLen  := 7 ELSE serWriteReq.readLen  := 8 END;
  1218.       IF 4 IN newstat.byte1 THEN serWriteReq.writeLen := 7 ELSE serWriteReq.writeLen := 8 END;
  1219.       serWriteReq.ioSer.command := se.setparams;
  1220.       IF e.DoIO(serWriteReq)#0 THEN RETURN -1 END;
  1221.     END;
  1222.     RETURN SYS.VAL(LONGINT,oldstat);
  1223.   END setserial;
  1224.  
  1225.  
  1226.   (* $SaveRegs+ *)
  1227.  
  1228.   PROCEDURE squery(): LONGINT;
  1229.   BEGIN
  1230.     ol.SetA5;
  1231.     (* $IF debug *)
  1232.     d.PrintF("squery\n");
  1233.     (* $END *)
  1234.     serWriteReq.ioSer.command := se.query;
  1235.     IF e.DoIO(serWriteReq)=0 THEN RETURN serWriteReq.ioSer.actual
  1236.                           ELSE RETURN -1 END;
  1237.   END squery;
  1238.  
  1239.  
  1240.   (* $SaveRegs+ *)
  1241.  
  1242.   PROCEDURE gets(prompt{8},buffer{9}: e.STRPTR): LONGINT;
  1243.     VAR name: e.STRING;
  1244.         ok: BOOLEAN;
  1245.   BEGIN
  1246.     ol.SetA5;
  1247.     (* $IF debug *)
  1248.     d.PrintF("gets\n");
  1249.     (* $END *)
  1250.     BlockWindow;
  1251.     ok := rt.GetString(buffer^,LEN(buffer^),prompt^,NIL,u.end);
  1252.     COPY(buffer^,protocolOpts);
  1253.     name := "xpr"; str.Append(name,config.protocol);
  1254.     IF d.SetVar(name,protocolOpts,-1,LONGSET{d.globalOnly}) THEN END;
  1255.     name := "ENVARC:"; str.Append(name,"xpr"); str.Append(name,config.protocol);
  1256.     IF d.SetVar(name,protocolOpts,-1,LONGSET{d.globalOnly}) THEN END;
  1257.     UnBlockWindow;
  1258.     IF ok THEN RETURN  0
  1259.           ELSE RETURN -1 END;
  1260.   END gets;
  1261.  
  1262.  
  1263.   (* $SaveRegs+ *)
  1264.  
  1265.   PROCEDURE getptr(typeofinfo{0}: LONGINT): e.APTR;
  1266.     VAR infotype: LONGINT;
  1267.   BEGIN
  1268.     infotype := typeofinfo;
  1269.     ol.SetA5;
  1270.     (* $IF debug *)
  1271.     d.PrintF("getptr\n");
  1272.     (* $END *)
  1273.     IF infotype = 1 THEN RETURN scr
  1274.                     ELSE RETURN  -1 END;
  1275.   END getptr;
  1276.  
  1277.   (* $StackChk= *)
  1278.  
  1279.  
  1280.   PROCEDURE XprSetup(VAR io: XPR.IO);
  1281.   BEGIN
  1282.     io.filename := NIL;
  1283.     io.fopen    := SYS.VAL(e.PROC,fopen);
  1284.     io.fclose   := SYS.VAL(e.PROC,fclose);
  1285.     io.fread    := SYS.VAL(e.PROC,fread);
  1286.     io.fwrite   := SYS.VAL(e.PROC,fwrite);
  1287.     io.sread    := SYS.VAL(e.PROC,sread);
  1288.     io.swrite   := SYS.VAL(e.PROC,swrite);
  1289.     io.sflush   := SYS.VAL(e.PROC,sflush);
  1290.     io.update   := SYS.VAL(e.PROC,update);
  1291.     io.chkabort := SYS.VAL(e.PROC,chkabort);
  1292.     io.chkmisc  := NIL;
  1293.     io.gets     := SYS.VAL(e.PROC,gets);
  1294.     io.setserial:= SYS.VAL(e.PROC,setserial);
  1295.     io.ffirst   := NIL;
  1296.     io.fnext    := NIL;
  1297.     io.finfo    := SYS.VAL(e.PROC,finfo);
  1298.     io.fseek    := SYS.VAL(e.PROC,fseek);
  1299.     io.extension:= 4;
  1300.     io.data     := NIL;
  1301.     io.options  := NIL;
  1302.     io.unlink   := SYS.VAL(e.PROC,unlink);
  1303.     io.squery   := SYS.VAL(e.PROC,squery);
  1304.     io.getptr   := SYS.VAL(e.PROC,getptr);
  1305.   END XprSetup;
  1306.  
  1307. (*----------------------- Menu Functions --------------------------*)
  1308.  
  1309.   PROCEDURE QuitFunc(code: INTEGER): BOOLEAN;
  1310.   BEGIN
  1311.     RETURN MyRequest("Request","Quit Termite?","Quit|Cancel",NIL) # 0;
  1312.   END QuitFunc;
  1313.  
  1314.  
  1315.   PROCEDURE AboutFunc(code: INTEGER): BOOLEAN;
  1316.   BEGIN
  1317.     (* $IF unreg *)
  1318.     IF MyRequest("Information","    Termite 1.0\n"
  1319.                                "   unregistered\n"
  1320.                                "      © 1993\n"
  1321.                                "by Christian Stiens\n"
  1322.                                "     SHAREWARE\n"
  1323.                                "All Rights Reserved"," OK ",NIL)=0 THEN END;
  1324.     (* $ELSE *)
  1325.     IF MyRequest("Information","    Termite 1.0\n"
  1326.                                " registered #00000\n"
  1327.                                "      © 1993\n"
  1328.                                "by Christian Stiens\n"
  1329.                                "     SHAREWARE\n"
  1330.                                "All Rights Reserved"," OK ",NIL)=0 THEN END;
  1331.     (* $END *)
  1332.     RETURN FALSE;
  1333.   END AboutFunc;
  1334.  
  1335.  
  1336.   PROCEDURE BaudFunc(code: INTEGER): BOOLEAN;
  1337.     VAR nr: INTEGER;
  1338.   BEGIN
  1339.     nr := I.SubNum(code);
  1340.     IF (nr<0) OR (nr >= LEN(baudRates)) THEN RETURN FALSE END;
  1341.     config.baud := baudRates[nr];
  1342.     ConfigToSer;
  1343.     RETURN FALSE;
  1344.   END BaudFunc;
  1345.  
  1346.  
  1347.   PROCEDURE BitsFunc(code: INTEGER): BOOLEAN;
  1348.   BEGIN
  1349.     CASE I.SubNum(code) OF
  1350.       0: config.bitsPerChar := 7;
  1351.     ELSE config.bitsPerChar := 8;
  1352.     END;
  1353.     ConfigToSer;
  1354.     RETURN FALSE;
  1355.   END BitsFunc;
  1356.  
  1357.  
  1358.   PROCEDURE StopBitsFunc(code: INTEGER): BOOLEAN;
  1359.   BEGIN
  1360.     CASE I.SubNum(code) OF
  1361.       1: config.stopBits := 2
  1362.     ELSE config.stopBits := 1
  1363.     END;
  1364.     ConfigToSer;
  1365.     RETURN FALSE;
  1366.   END StopBitsFunc;
  1367.  
  1368.  
  1369.   PROCEDURE DuplexFunc(code: INTEGER): BOOLEAN;
  1370.   BEGIN
  1371.     CASE I.SubNum(code) OF
  1372.       0: config.duplex := halfduplex
  1373.     | 1: config.duplex := fullduplex
  1374.     ELSE
  1375.     END;
  1376.     RETURN FALSE;
  1377.   END DuplexFunc;
  1378.  
  1379.  
  1380.   PROCEDURE InputBufFunc(code: INTEGER): BOOLEAN;
  1381.     VAR nr: INTEGER;
  1382.   BEGIN
  1383.     nr := I.SubNum(code);
  1384.     IF (nr<0) OR (nr >= LEN(bufSizes)) THEN RETURN FALSE END;
  1385.     config.rBufLen := bufSizes[nr];
  1386.     ConfigToSer;
  1387.     RETURN FALSE;
  1388.   END InputBufFunc;
  1389.  
  1390.  
  1391.   PROCEDURE HandshakeFunc(code: INTEGER): BOOLEAN;
  1392.   BEGIN
  1393.     CASE I.SubNum(code) OF
  1394.       none..ctsrts: config.handShaking := SHORT(I.SubNum(code));
  1395.     ELSE RETURN FALSE
  1396.     END;
  1397.     ConfigToSer;
  1398.     RETURN FALSE;
  1399.   END HandshakeFunc;
  1400.  
  1401.  
  1402.   PROCEDURE ParityFunc(code: INTEGER): BOOLEAN;
  1403.   BEGIN
  1404.     CASE I.SubNum(code) OF
  1405.       none..space: config.parity := SHORT(I.SubNum(code));
  1406.     ELSE RETURN FALSE
  1407.     END;
  1408.     ConfigToSer;
  1409.     RETURN FALSE;
  1410.   END ParityFunc;
  1411.  
  1412.  
  1413.   PROCEDURE RadboogieFunc(code: INTEGER): BOOLEAN;
  1414.   BEGIN
  1415.     config.radBoogie := I.checked IN SYS.VAL(I.MenuItemPtr,I.ItemAddress(menu^,code)).flags;
  1416.     ConfigToSer;
  1417.     RETURN FALSE;
  1418.   END RadboogieFunc;
  1419.  
  1420.  
  1421.   PROCEDURE HangUpFunc(code: INTEGER): BOOLEAN;
  1422.   BEGIN
  1423.     SerWriteString(config.hangupString);
  1424.     RETURN FALSE
  1425.   END HangUpFunc;
  1426.  
  1427.  
  1428.   PROCEDURE InitFunc(code: INTEGER): BOOLEAN;
  1429.   BEGIN
  1430.     SerWriteString(config.initString);
  1431.     RETURN FALSE
  1432.   END InitFunc;
  1433.  
  1434.  
  1435.   PROCEDURE InitStringFunc(code: INTEGER): BOOLEAN;
  1436.   BEGIN
  1437.     BlockWindow;
  1438.     IF rt.GetString(config.initString,LEN(config.initString),"Enter Init-String",NIL,u.end) THEN END;
  1439.     UnBlockWindow;
  1440.     RETURN FALSE
  1441.   END InitStringFunc;
  1442.  
  1443.  
  1444.   PROCEDURE HangupStringFunc(code: INTEGER): BOOLEAN;
  1445.   BEGIN
  1446.     BlockWindow;
  1447.     IF rt.GetString(config.hangupString,LEN(config.hangupString),"Enter Hangup-String",NIL,u.end) THEN END;
  1448.     UnBlockWindow;
  1449.     RETURN FALSE
  1450.   END HangupStringFunc;
  1451.  
  1452.  
  1453.  
  1454.   PROCEDURE WriteString(VAR file: fs.File; head,txt: ARRAY OF CHAR; quote: BOOLEAN); (* $CopyArrays- *)
  1455.     VAR string: e.STRING;
  1456.   BEGIN
  1457.     COPY(head,string);
  1458.     WHILE str.Length(string) < 16 DO str.Append(string," ") END;
  1459.     IF quote THEN str.Append(string,'"') END;
  1460.     str.Append(string,txt);
  1461.     IF quote THEN str.Append(string,'"') END;
  1462.     IF (file.status=fs.ok) & fs.WriteString(file,string) THEN END;
  1463.   END WriteString;
  1464.  
  1465.   PROCEDURE WriteInt(VAR file: fs.File; head: ARRAY OF CHAR; n: LONGINT); (* $CopyArrays- *)
  1466.     VAR int: ARRAY 16 OF CHAR;
  1467.   BEGIN
  1468.     e.RawDoFmt("%ld",SYS.ADR(n),RFProc,SYS.ADR(int));
  1469.     WriteString(file,head,int,FALSE);
  1470.   END WriteInt;
  1471.  
  1472.   PROCEDURE WriteBool(VAR file: fs.File; head: ARRAY OF CHAR; flag: BOOLEAN); (* $CopyArrays- *)
  1473.     VAR string: ARRAY 8 OF CHAR;
  1474.   BEGIN
  1475.     IF flag THEN string := "TRUE" ELSE string := "FALSE" END;
  1476.     WriteString(file,head,string,FALSE);
  1477.   END WriteBool;
  1478.  
  1479.   PROCEDURE WriteEnum(VAR file: fs.File; head: ARRAY OF CHAR; int: INTEGER; enum: ARRAY OF CHAR); (* $CopyArrays- *)
  1480.     VAR txt: ARRAY 16 OF CHAR;
  1481.         i,j: INTEGER;
  1482.   BEGIN
  1483.     j := 0;
  1484.     FOR i := 1 TO int DO
  1485.       WHILE (enum[j]#0X) & (enum[j]#"|") DO INC(j) END;
  1486.       IF enum[j]="|" THEN INC(j) END;
  1487.     END;
  1488.     i := 0;
  1489.     WHILE (enum[j]#0X) & (enum[j]#"|") DO
  1490.       txt[i] := enum[j];
  1491.       INC(i); INC(j);
  1492.     END;
  1493.     txt[i] := 0X;
  1494.     WriteString(file,head,txt,FALSE);
  1495.   END WriteEnum;
  1496.  
  1497.  
  1498.   PROCEDURE SaveConfigFunc(code: INTEGER): BOOLEAN;
  1499.     VAR name: e.STRING;
  1500.         file: fs.File;
  1501.         i,n: INTEGER;
  1502.   BEGIN
  1503.     BlockWindow;
  1504.     fr.okText := "Save";
  1505.     fr.pattern := "~(#?.info)";
  1506.     name := "Termite.config";
  1507.     IF fr.FileReqWinSave("Save Config",name,win) THEN
  1508.       IF fs.Open(file,name,TRUE) THEN
  1509.         IF fs.WriteString(file,"; Termite Configuration\n") THEN END;
  1510.         WriteString(file,"DEVICE"       ,config.device,TRUE);
  1511.         WriteInt   (file,"UNIT"         ,config.unit);
  1512.         WriteInt   (file,"BUFFER"       ,config.rBufLen);
  1513.         WriteInt   (file,"BAUDRATE"     ,config.baud);
  1514.         WriteInt   (file,"BREAKTIME"    ,config.breakTime);
  1515.         WriteInt   (file,"BITSPERCHAR"  ,config.bitsPerChar);
  1516.         WriteInt   (file,"STOPBITS"     ,config.stopBits);
  1517.         WriteEnum  (file,"PARITY"       ,config.parity,"NONE|EVEN|ODD|MARK|SPACE|");
  1518.         WriteEnum  (file,"HANDSHAKING"  ,config.handShaking,"NONE|XONXOFF|7WIRE|");
  1519.         WriteBool  (file,"RADBOOGIE"    ,config.radBoogie);
  1520.         WriteEnum  (file,"DUPLEX"       ,config.duplex,"HALF|FULL|");
  1521.         WriteString(file,"INITSTRING"   ,config.initString,TRUE);
  1522.         WriteString(file,"HANGUPSTRING" ,config.hangupString,TRUE);
  1523.         WriteInt   (file,"TIMEFORCONNECT",config.time4connect);
  1524.         WriteString(file,"PROTOCOL"     ,config.protocol,TRUE);
  1525.         WriteString(file,"CAPTURE"      ,config.capture,TRUE);
  1526.         WriteString(file,"DOWNLOADDIR"  ,config.downloadDir,TRUE);
  1527.         WriteString(file,"UPLOADDIR"    ,config.uploadDir,TRUE);
  1528.         WriteString(file,"PASTEDIR"     ,config.pasteDir,TRUE);
  1529.         WriteInt   (file,"PASTEDELAY"   ,config.pasteDelay);
  1530.         WriteInt   (file,"SCREENDEPTH"  ,config.screenDepth);
  1531.         FOR i := 0 TO ASH(LONG(1),scr.rastPort.bitMap.depth)-1 DO
  1532.           n := g.GetRGB4(scr.viewPort.colorMap,i);
  1533.           e.RawDoFmt("%03x,",SYS.ADR(n),RFProc,SYS.ADR(name[i*4]));
  1534.         END;
  1535.         IF i>0 THEN name[i*4-1] := 0X END;
  1536.         WriteString(file,"PALETTE"      ,name,FALSE);
  1537.         WriteString(file,"FONT"         ,config.font,TRUE);
  1538.         WriteString(file,"KEYMAP"       ,config.keyMap,TRUE);
  1539.         WriteInt   (file,"PRIORITY"     ,config.priority);
  1540.  
  1541.         IF fs.Close(file) THEN END;
  1542.       END;
  1543.     END;
  1544.     UnBlockWindow;
  1545.     RETURN FALSE
  1546.   END SaveConfigFunc;
  1547.  
  1548.  
  1549.   PROCEDURE ProtocolFunc(code: INTEGER): BOOLEAN;
  1550.     VAR n: LONGINT;
  1551.         name: e.STRING;
  1552.         xprname: ARRAY 80 OF CHAR;
  1553.         nochmal: BOOLEAN;
  1554.   BEGIN
  1555.     name := "LIBS:";
  1556.     BlockWindow;
  1557.     fr.pattern := "xpr#?.library";
  1558.     fr.okText := "Select";
  1559.     fr.patGad := FALSE;
  1560.     REPEAT
  1561.       nochmal := FALSE;
  1562.       IF fr.FileReqWin("Select Protocol",name,win) THEN
  1563.         COPY(d.FilePart(name)^,xprname);
  1564.         str.Delete(xprname,0,3);
  1565.         FOR n := 0 TO str.Length(xprname)-1 DO
  1566.           IF xprname[n]="." THEN xprname[n] := 0X END;
  1567.         END;
  1568.         CASE OpenProtocol(xprname) OF
  1569.           cantLoadProtocol:  nochmal := MyRequest("Information","Can't load Protocol", "Retry|Cancel",NIL)#0;
  1570.         | cantSetupProtocol: nochmal := MyRequest("Information","Can't setup Protocol","Retry|Cancel",NIL)#0;
  1571.         ELSE
  1572.           COPY(xprname,config.protocol);
  1573.         END;
  1574.       END;
  1575.     UNTIL ~nochmal;
  1576.     fr.patGad := TRUE;
  1577.     UnBlockWindow;
  1578.     RETURN FALSE
  1579.   END ProtocolFunc;
  1580.  
  1581.  
  1582.   PROCEDURE OptionsFunc(code: INTEGER): BOOLEAN;
  1583.   BEGIN
  1584.     IF XPR.base#NIL THEN
  1585.       xprio.filename := NIL;
  1586.       IF XPR.success IN XPR.XProtocolSetup(xprio^) THEN END;
  1587.     END;
  1588.     RETURN FALSE
  1589.   END OptionsFunc;
  1590.  
  1591.  
  1592.   PROCEDURE DownloadFunc(code: INTEGER): BOOLEAN;
  1593.     VAR name: e.STRING;
  1594.         lock,oldCD: d.FileLockPtr;
  1595.   BEGIN
  1596.     name := "";
  1597.     lock := NIL;
  1598.     BlockWindow;
  1599.     IF config.downloadDir # "" THEN
  1600.       lock := d.Lock(config.downloadDir,d.sharedLock);
  1601.       IF lock#NIL THEN oldCD := d.CurrentDir(lock) END;
  1602.     END;
  1603.     IF XPR.base=NIL THEN
  1604.       IF ProtocolFunc(0) THEN END;
  1605.     END;
  1606.     IF XPR.base#NIL THEN
  1607.       IF XPR.norecreq IN xprFlags THEN
  1608.         xprio.filename := NIL;
  1609.         Transfer(FALSE);
  1610.       ELSE
  1611.         fr.pattern := "~(#?.info)";
  1612.         fr.okText := "Downld";
  1613.         IF fr.FileReqWin("Download File",name,win) THEN
  1614.           xprio.filename := SYS.ADR(name);
  1615.           Transfer(FALSE);
  1616.         END;
  1617.       END;
  1618.     END;
  1619.     IF lock # NIL THEN oldCD := d.CurrentDir(oldCD); d.UnLock(lock) END;
  1620.     UnBlockWindow;
  1621.     RETURN FALSE
  1622.   END DownloadFunc;
  1623.  
  1624.  
  1625.   PROCEDURE UploadFunc(code: INTEGER): BOOLEAN;
  1626.     VAR name : e.STRING;
  1627.         lock,oldCD : d.FileLockPtr;
  1628.   BEGIN
  1629.     name := "";
  1630.     lock := NIL;
  1631.     BlockWindow;
  1632.     IF config.uploadDir # "" THEN
  1633.       lock := d.Lock(config.uploadDir,d.sharedLock);
  1634.       IF lock#NIL THEN oldCD := d.CurrentDir(lock) END;
  1635.     END;
  1636.     IF XPR.base=NIL THEN
  1637.       IF ProtocolFunc(0) THEN END;
  1638.     END;
  1639.     IF XPR.base#NIL THEN
  1640.       IF XPR.nosndreq IN xprFlags THEN
  1641.         xprio.filename := NIL;
  1642.         Transfer(TRUE);
  1643.       ELSE
  1644.         fr.pattern := "~(#?.info)";
  1645.         fr.okText := "Upload";
  1646.         IF fr.FileReqWin("Upload File",name,win) THEN
  1647.           xprio.filename := SYS.ADR(name);
  1648.           Transfer(TRUE);
  1649.         END;
  1650.       END;
  1651.     END;
  1652.     IF lock # NIL THEN oldCD := d.CurrentDir(oldCD); d.UnLock(lock) END;
  1653.     UnBlockWindow;
  1654.     RETURN FALSE
  1655.   END UploadFunc;
  1656.  
  1657.  
  1658.   PROCEDURE DialFunc(code: INTEGER): BOOLEAN;
  1659.     VAR
  1660.       item: I.MenuItemPtr;
  1661.       nr: INTEGER;
  1662.   BEGIN
  1663.     IF I.MenuNum(code)=4 THEN
  1664.       nr := lastDialNr
  1665.     ELSE
  1666.       nr := I.ItemNum(code);
  1667.       IF lastDialNr = -1 THEN
  1668.          I.OnMenu(win,I.UIntToLong(I.FullMenuNum(4,2,I.noSub)));
  1669.       END;
  1670.     END;
  1671.     IF (nr >= 0) & (nr < LEN(dialArray)) THEN
  1672.       SerWriteString(dialArray[nr]^);
  1673.       lastDialNr := nr;
  1674.     END;
  1675.     RETURN FALSE
  1676.   END DialFunc;
  1677.  
  1678.  
  1679.   PROCEDURE BreakFunc(code: INTEGER): BOOLEAN;
  1680.   BEGIN
  1681.     serWriteReq.ioSer.command := se.break;
  1682.     ioErr := e.DoIO(serWriteReq);
  1683.     RETURN FALSE
  1684.   END BreakFunc;
  1685.  
  1686.  
  1687.   PROCEDURE ClearFunc(code: INTEGER): BOOLEAN;
  1688.   BEGIN
  1689.     conWriteReq.data := SYS.ADR("\x0C");
  1690.     conWriteReq.length := -1;
  1691.     conWriteReq.command := e.write;
  1692.     e.OldDoIO(conWriteReq);
  1693.     RETURN FALSE
  1694.   END ClearFunc;
  1695.  
  1696.  
  1697.   PROCEDURE ResetFunc(code: INTEGER): BOOLEAN;
  1698.   BEGIN
  1699.     conWriteReq.data := SYS.ADR("\ec\[1}");
  1700.     conWriteReq.length := -1;
  1701.     conWriteReq.command := e.write;
  1702.     e.OldDoIO(conWriteReq);
  1703.     RETURN FALSE
  1704.   END ResetFunc;
  1705.  
  1706.  
  1707.   PROCEDURE ColorsFunc(code: INTEGER): BOOLEAN;
  1708.     VAR res: LONGINT;
  1709.   BEGIN
  1710.     BlockWindow;
  1711.     res := rt.PaletteRequest("Change Palette",NIL,u.end);
  1712.     UnBlockWindow;
  1713.     RETURN FALSE
  1714.   END ColorsFunc;
  1715.  
  1716.  
  1717.   PROCEDURE BreakTimeFunc(code: INTEGER): BOOLEAN;
  1718.   BEGIN
  1719.     BlockWindow;
  1720.     REPEAT
  1721.       IF ~rt.GetLong(config.breakTime,"Enter Break-Time (µs)",NIL,rt.glWidth,250,u.end) THEN END;
  1722.     UNTIL (config.breakTime>0)&(config.breakTime<5000000);
  1723.     ConfigToSer;
  1724.     UnBlockWindow;
  1725.     RETURN FALSE
  1726.   END BreakTimeFunc;
  1727.  
  1728.  
  1729.   PROCEDURE PasteDelayFunc(code: INTEGER): BOOLEAN;
  1730.   BEGIN
  1731.     BlockWindow;
  1732.     REPEAT
  1733.       IF ~rt.GetLong(config.pasteDelay,"Enter Paste-Delay (ms)",NIL,rt.glWidth,250,u.end) THEN END;
  1734.     UNTIL (config.pasteDelay >= 0) & (config.pasteDelay <= 1000);
  1735.     UnBlockWindow;
  1736.     RETURN FALSE
  1737.   END PasteDelayFunc;
  1738.  
  1739.  
  1740.   PROCEDURE Paste(text: e.APTR; size: LONGINT);
  1741.     VAR
  1742.       ch: CHAR;
  1743.       i,n: LONGINT;
  1744.       msg: I.IntuiMessagePtr;
  1745.       txt: UNTRACED POINTER TO ARRAY 0FFFFFFFH OF CHAR;
  1746.   BEGIN
  1747.     txt := text;
  1748.     IF size > 0 THEN
  1749.       AbortReadReq;
  1750.  
  1751.       FOR i := 0 TO size-1 DO
  1752.         ch := txt[i];
  1753.         IF ch = "\n" THEN ch := "\r" END;
  1754.  
  1755.         serWriteReq.ioSer.data := SYS.ADR(ch);
  1756.         serWriteReq.ioSer.length := 1;
  1757.         serWriteReq.ioSer.command := e.write;
  1758.         ioErr := e.DoIO(serWriteReq);
  1759.  
  1760.         IF config.duplex=halfduplex THEN
  1761.           conWriteReq.length  := 1;
  1762.           conWriteReq.data    := SYS.ADR(ch);
  1763.           conWriteReq.command := e.write;
  1764.           e.OldDoIO(conWriteReq);
  1765.           Capture(SYS.ADR(ch),1);
  1766.         END;
  1767.  
  1768.         n := sread(SYS.VAL(e.STRPTR,readBuf),readBufLen,0);
  1769.         IF n > 0 THEN
  1770.           conWriteReq.length  := n;
  1771.           conWriteReq.data    := readBuf;
  1772.           conWriteReq.command := e.write;
  1773.           e.OldDoIO(conWriteReq);
  1774.           Capture(readBuf,n);
  1775.         END;
  1776.  
  1777.         timeReq.time.secs  :=  config.pasteDelay DIV 1000;
  1778.         timeReq.time.micro := (config.pasteDelay * 1000) MOD 1000000;
  1779.         IF config.pasteDelay > 0 THEN
  1780.           timeReq.node.command := ti.addRequest;
  1781.           e.OldDoIO(timeReq);
  1782.         END;
  1783.  
  1784.         LOOP
  1785.           msg := gt.GetIMsg(win.userPort);
  1786.           IF msg=NIL THEN EXIT END;
  1787.           IF I.menuPick IN msg.class THEN
  1788.             IF MyRequest("Request","Abort Paste?","Abort|Cancel",NIL)#0 THEN
  1789.               i := size;
  1790.             END;
  1791.           END;
  1792.           gt.ReplyIMsg(msg);
  1793.         END;
  1794.  
  1795.       END;
  1796.       SendReadReq;
  1797.     END;
  1798.   END Paste;
  1799.  
  1800.  
  1801.   PROCEDURE PasteClipboardFunc(code: INTEGER): BOOLEAN;
  1802.     VAR name: e.STRING;
  1803.         text: e.APTR;
  1804.         size: LONGINT;
  1805.   BEGIN
  1806.     BlockWindow;
  1807.     IF cbt.Paste(size,text) THEN
  1808.       Paste(text,size);
  1809.       DISPOSE(text)
  1810.     END;
  1811.     UnBlockWindow;
  1812.     RETURN FALSE
  1813.   END PasteClipboardFunc;
  1814.  
  1815.  
  1816.   PROCEDURE PasteFileFunc(code: INTEGER): BOOLEAN;
  1817.     VAR name: e.STRING;
  1818.         text: e.APTR;
  1819.         size: LONGINT;
  1820.         file: fs.File;
  1821.         lock,oldCD: d.FileLockPtr;
  1822.   BEGIN
  1823.     name := "";
  1824.     lock := NIL;
  1825.     BlockWindow;
  1826.     IF config.pasteDir # "" THEN
  1827.       lock := d.Lock(config.pasteDir,d.sharedLock);
  1828.       IF lock#NIL THEN oldCD := d.CurrentDir(lock) END;
  1829.     END;
  1830.     fr.pattern := "~(#?.info)";
  1831.     fr.okText := "Paste";
  1832.     IF fr.FileReqWin("Paste File",name,win) THEN
  1833.       IF fs.Open(file,name,FALSE) THEN
  1834.         size := fs.Size(file);
  1835.         IF size > 0 THEN
  1836.           ol.Allocate(text,size);
  1837.           IF text#NIL THEN
  1838.             IF fs.ReadBlock(file,text,size) THEN
  1839.               Paste(text,size);
  1840.             END;
  1841.             DISPOSE(text)
  1842.           END;
  1843.         END;
  1844.         IF fs.Close(file) THEN END;
  1845.       END;
  1846.     END;
  1847.     IF lock # NIL THEN oldCD := d.CurrentDir(oldCD); d.UnLock(lock) END;
  1848.     UnBlockWindow;
  1849.     RETURN FALSE
  1850.   END PasteFileFunc;
  1851.  
  1852.  
  1853. (*------------------------- Menu Handler --------------------------*)
  1854.  
  1855.  
  1856.   PROCEDURE HandleMenuEvent (code: INTEGER): BOOLEAN;
  1857.     TYPE
  1858.       MenuFunc = PROCEDURE(code: INTEGER): BOOLEAN;
  1859.     VAR
  1860.       item: I.MenuItemPtr;
  1861.       func: MenuFunc;
  1862.       end: BOOLEAN;
  1863.   BEGIN
  1864.     end := FALSE;
  1865.     WHILE (code # I.menuNull) & ~end DO
  1866.       item := I.ItemAddress(menu^, code);
  1867.       func := SYS.VAL(MenuFunc,gt.MenuItemUserData(item));
  1868.       IF func # NIL THEN
  1869.         end := func(code)
  1870.       END;
  1871.       code := item.nextSelect;
  1872.     END;
  1873.     RETURN end;
  1874.   END HandleMenuEvent;
  1875.  
  1876.  
  1877. (*---------------------------- New Menu ---------------------------*)
  1878.  
  1879.   CONST
  1880.     menuBaud        = 15; itemsBaud = 12;
  1881.     menuBufLen      = 28; itemsBufLen = 8;
  1882.     menuHandShake   = 37;
  1883.     menuParity      = 41;
  1884.     menuBitsPerChar = 47;
  1885.     menuStopBits    = 50;
  1886.     menuDuplex      = 53;
  1887.     menuRadboogie   = 59;
  1888.     menuOptions     = 74;
  1889.     menuDial        = 75;
  1890.  
  1891.   CONST
  1892.     NewMenu = NewMenuType(
  1893. (*0*) gt.title, SYS.ADR("Project"),     NIL,         {},  LONGSET{}, NIL,
  1894.       gt.item , SYS.ADR("Save Config..."),SYS.ADR("S"),{},LONGSET{}, SYS.VAL(e.APTR,SaveConfigFunc),
  1895.       gt.item , SYS.ADR("About..."),    NIL,         {},  LONGSET{}, SYS.VAL(e.APTR,AboutFunc),
  1896.       gt.item , gt.barLabel,            NIL,         {},  LONGSET{}, NIL,
  1897.       gt.item , SYS.ADR("Quit"),        SYS.ADR("Q"),{},  LONGSET{}, SYS.VAL(e.APTR,QuitFunc),
  1898.  
  1899. (*5*) gt.title, SYS.ADR("Edit"),        NIL,         {},  LONGSET{}, NIL,
  1900.       gt.item , SYS.ADR("Paste Clip"),  SYS.ADR("V"),{},  LONGSET{}, SYS.VAL(e.APTR,PasteClipboardFunc),
  1901.       gt.item , SYS.ADR("Paste File..."),SYS.ADR("F"),{}, LONGSET{}, SYS.VAL(e.APTR,PasteFileFunc),
  1902.       gt.item , gt.barLabel,            NIL,         {},  LONGSET{}, NIL,
  1903.       gt.item , SYS.ADR("Delay..."),    NIL,         {},  LONGSET{}, SYS.VAL(e.APTR,PasteDelayFunc),
  1904.  
  1905. (*8*) gt.title, SYS.ADR("Screen"),      NIL,         {},  LONGSET{}, NIL,
  1906.       gt.item , SYS.ADR("Palette..."),  SYS.ADR("P"),{},  LONGSET{}, SYS.VAL(e.APTR,ColorsFunc),
  1907.       gt.item , SYS.ADR("Clear"),       SYS.ADR("L"),{},  LONGSET{}, SYS.VAL(e.APTR,ClearFunc),
  1908.       gt.item , SYS.ADR("Reset"),       SYS.ADR("R"),{},  LONGSET{}, SYS.VAL(e.APTR,ResetFunc),
  1909.  
  1910. (*14*)gt.title, SYS.ADR("Serial"),      NIL,         {},  LONGSET{}, NIL,
  1911.  
  1912.       gt.item , SYS.ADR("Baud Rate"),   NIL,         {},  LONGSET{}, NIL,
  1913.       gt.sub ,  SYS.ADR("110"),         NIL,         {I.checkIt},          -LONGSET{0}, SYS.VAL(e.APTR,BaudFunc),
  1914.       gt.sub ,  SYS.ADR("300"),         NIL,         {I.checkIt},          -LONGSET{1}, SYS.VAL(e.APTR,BaudFunc),
  1915.       gt.sub ,  SYS.ADR("1200"),        NIL,         {I.checkIt},          -LONGSET{2}, SYS.VAL(e.APTR,BaudFunc),
  1916.       gt.sub ,  SYS.ADR("2400"),        NIL,         {I.checkIt},          -LONGSET{3}, SYS.VAL(e.APTR,BaudFunc),
  1917.       gt.sub ,  SYS.ADR("4800"),        NIL,         {I.checkIt},          -LONGSET{4}, SYS.VAL(e.APTR,BaudFunc),
  1918.       gt.sub ,  SYS.ADR("9600"),        NIL,         {I.checkIt},          -LONGSET{5}, SYS.VAL(e.APTR,BaudFunc),
  1919.       gt.sub ,  SYS.ADR("19200"),       NIL,         {I.checkIt},          -LONGSET{6}, SYS.VAL(e.APTR,BaudFunc),
  1920.       gt.sub ,  SYS.ADR("31250"),       NIL,         {I.checkIt},          -LONGSET{7}, SYS.VAL(e.APTR,BaudFunc),
  1921.       gt.sub ,  SYS.ADR("38400"),       NIL,         {I.checkIt},          -LONGSET{8}, SYS.VAL(e.APTR,BaudFunc),
  1922.       gt.sub ,  SYS.ADR("57600"),       NIL,         {I.checkIt},          -LONGSET{9}, SYS.VAL(e.APTR,BaudFunc),
  1923.       gt.sub ,  SYS.ADR("76800"),       NIL,         {I.checkIt},          -LONGSET{10},SYS.VAL(e.APTR,BaudFunc),
  1924.       gt.sub ,  SYS.ADR("115200"),      NIL,         {I.checkIt},          -LONGSET{11},SYS.VAL(e.APTR,BaudFunc),
  1925.  
  1926. (*28*)gt.item , SYS.ADR("Buffer Size"), NIL,    {},                    LONGSET{},  NIL,
  1927.       gt.sub ,  SYS.ADR("512"),         NIL,         {I.checkIt},          -LONGSET{0}, SYS.VAL(e.APTR,InputBufFunc),
  1928.       gt.sub ,  SYS.ADR("1024"),        NIL,         {I.checkIt},          -LONGSET{1}, SYS.VAL(e.APTR,InputBufFunc),
  1929.       gt.sub ,  SYS.ADR("2048"),        NIL,         {I.checkIt},          -LONGSET{2}, SYS.VAL(e.APTR,InputBufFunc),
  1930.       gt.sub ,  SYS.ADR("4096"),        NIL,         {I.checkIt},          -LONGSET{3}, SYS.VAL(e.APTR,InputBufFunc),
  1931.       gt.sub ,  SYS.ADR("8192"),        NIL,         {I.checkIt},          -LONGSET{4}, SYS.VAL(e.APTR,InputBufFunc),
  1932.       gt.sub ,  SYS.ADR("16384"),       NIL,         {I.checkIt},          -LONGSET{5}, SYS.VAL(e.APTR,InputBufFunc),
  1933.       gt.sub ,  SYS.ADR("32768"),       NIL,         {I.checkIt},          -LONGSET{6}, SYS.VAL(e.APTR,InputBufFunc),
  1934.       gt.sub ,  SYS.ADR("65536"),       NIL,         {I.checkIt},          -LONGSET{7}, SYS.VAL(e.APTR,InputBufFunc),
  1935.  
  1936. (*37*)gt.item , SYS.ADR("Handshaking"), NIL,         {},  LONGSET{}, NIL,
  1937.       gt.sub ,  SYS.ADR("None"),        NIL,         {I.checkIt},          -LONGSET{0}, SYS.VAL(e.APTR,HandshakeFunc),
  1938.       gt.sub ,  SYS.ADR("XON/XOFF"),    NIL,         {I.checkIt},          -LONGSET{1}, SYS.VAL(e.APTR,HandshakeFunc),
  1939.       gt.sub ,  SYS.ADR("RTS/CTS"),     NIL,         {I.checkIt},          -LONGSET{2}, SYS.VAL(e.APTR,HandshakeFunc),
  1940.  
  1941. (*41*)gt.item , SYS.ADR("Parity"),      NIL,         {},  LONGSET{}, NIL,
  1942.       gt.sub ,  SYS.ADR("None"),        NIL,         {I.checkIt},          -LONGSET{0}, SYS.VAL(e.APTR,ParityFunc),
  1943.       gt.sub ,  SYS.ADR("Even"),        NIL,         {I.checkIt},          -LONGSET{1}, SYS.VAL(e.APTR,ParityFunc),
  1944.       gt.sub ,  SYS.ADR("Odd"),         NIL,         {I.checkIt},          -LONGSET{2}, SYS.VAL(e.APTR,ParityFunc),
  1945.       gt.sub ,  SYS.ADR("Mark"),        NIL,         {I.checkIt},          -LONGSET{3}, SYS.VAL(e.APTR,ParityFunc),
  1946.       gt.sub ,  SYS.ADR("Space"),       NIL,         {I.checkIt},          -LONGSET{4}, SYS.VAL(e.APTR,ParityFunc),
  1947.  
  1948. (*47*)gt.item , SYS.ADR("Bits/Char"),   NIL,         {},  LONGSET{}, NIL,
  1949.       gt.sub ,  SYS.ADR("7"),           NIL,         {I.checkIt},          -LONGSET{0}, SYS.VAL(e.APTR,BitsFunc),
  1950.       gt.sub ,  SYS.ADR("8"),           NIL,         {I.checkIt},          -LONGSET{1}, SYS.VAL(e.APTR,BitsFunc),
  1951.  
  1952. (*50*)gt.item , SYS.ADR("Stop Bits"),   NIL,         {},  LONGSET{}, NIL,
  1953.       gt.sub ,  SYS.ADR("1"),           NIL,         {I.checkIt},          -LONGSET{0}, SYS.VAL(e.APTR,StopBitsFunc),
  1954.       gt.sub ,  SYS.ADR("2"),           NIL,         {I.checkIt},          -LONGSET{1}, SYS.VAL(e.APTR,StopBitsFunc),
  1955.  
  1956. (*53*)gt.item , SYS.ADR("Duplex"),      NIL,         {},  LONGSET{}, NIL,
  1957.       gt.sub ,  SYS.ADR("Half"),        NIL,         {I.checkIt},          -LONGSET{0}, SYS.VAL(e.APTR,DuplexFunc),
  1958.       gt.sub ,  SYS.ADR("Full"),        NIL,         {I.checkIt},          -LONGSET{1}, SYS.VAL(e.APTR,DuplexFunc),
  1959.  
  1960.       gt.item , gt.barLabel,            NIL,         {},  LONGSET{}, NIL,
  1961.  
  1962. (*57*)gt.item , SYS.ADR("Break Time..."),      NIL,  {},                       LONGSET{}, SYS.VAL(e.APTR,BreakTimeFunc),
  1963.       gt.item , gt.barLabel,            NIL,         {},  LONGSET{}, NIL,
  1964. (*59*)gt.item , SYS.ADR("Rad Boogie"),  NIL,         {I.checkIt,I.menuToggle}, LONGSET{}, SYS.VAL(e.APTR,RadboogieFunc),
  1965.  
  1966. (*60*)gt.title, SYS.ADR("Modem"),       NIL,         {},  LONGSET{}, NIL,
  1967.       gt.item , SYS.ADR("Hang Up"),     SYS.ADR("H"),{},  LONGSET{}, SYS.VAL(e.APTR,HangUpFunc),
  1968.       gt.item , SYS.ADR("Init"),        SYS.ADR("I"),{},  LONGSET{}, SYS.VAL(e.APTR,InitFunc),
  1969.       gt.item , SYS.ADR("Redial"),      SYS.ADR("E"),{gt.itemDisabled},  LONGSET{}, SYS.VAL(e.APTR,DialFunc),
  1970.       gt.item , gt.barLabel,            NIL,         {},  LONGSET{}, NIL,
  1971.       gt.item , SYS.ADR("Send Break"),  SYS.ADR("B"),{},  LONGSET{}, SYS.VAL(e.APTR,BreakFunc),
  1972.       gt.item , gt.barLabel,            NIL,         {},  LONGSET{}, NIL,
  1973.       gt.item , SYS.ADR("Hangup String..."), NIL,    {},  LONGSET{}, SYS.VAL(e.APTR,HangupStringFunc),
  1974.       gt.item , SYS.ADR("Init String..."),   NIL,    {},  LONGSET{}, SYS.VAL(e.APTR,InitStringFunc),
  1975.  
  1976. (*69*)gt.title, SYS.ADR("Transfer"),    NIL,         {},  LONGSET{}, NIL,
  1977.       gt.item , SYS.ADR("Download..."), SYS.ADR("D"),{},  LONGSET{}, SYS.VAL(e.APTR,DownloadFunc),
  1978.       gt.item , SYS.ADR("Upload..."),   SYS.ADR("U"),{},  LONGSET{}, SYS.VAL(e.APTR,UploadFunc),
  1979.       gt.item , gt.barLabel,            NIL,         {},  LONGSET{}, NIL,
  1980.       gt.item , SYS.ADR("Protocol..."), NIL,         {},  LONGSET{}, SYS.VAL(e.APTR,ProtocolFunc),
  1981.       gt.item , SYS.ADR("Options..."),  SYS.ADR("O"),{},  LONGSET{}, SYS.VAL(e.APTR,OptionsFunc),
  1982.  
  1983. (*75*)gt.title, SYS.ADR("Dial"),        NIL,         {},  LONGSET{}, NIL,
  1984.  
  1985.       gt.end  , NIL,                    NIL,         {},  LONGSET{}, NIL);
  1986.  
  1987.  
  1988.   PROCEDURE LoadPhoneBook;
  1989.     CONST
  1990.        commKeys = "1\o2\o3\o4\o5\o6\o7\o8\o9\o0\o";
  1991.     VAR
  1992.       file: fs.File;
  1993.       entry: LONGINT;
  1994.       string: e.STRING;
  1995.   BEGIN
  1996.     IF args.phonebook # NIL THEN
  1997.       COPY(args.phonebook^,string);
  1998.     ELSE
  1999.       string := "Termite.phonebook";
  2000.       IF ~fs.Exists(string) THEN
  2001.         string := "PROGDIR:Termite.phonebook";
  2002.         IF resident OR ~fs.Exists(string) THEN
  2003.           string := "ENV:Termite.phonebook";
  2004.           IF ~fs.Exists(string) THEN
  2005.             string := "s:Termite.phonebook";
  2006.             IF ~fs.Exists(string) THEN
  2007.               string := ""
  2008.             END;
  2009.           END;
  2010.         END;
  2011.       END;
  2012.     END;
  2013.     entry := 0;
  2014.     IF fs.Open(file,string,FALSE) THEN
  2015.       WHILE fs.ReadString(file,string) & (entry < maxDialEntries) DO
  2016.         IF RemSpaces(string) THEN
  2017.           NEW(dialArray[entry]);
  2018.           NEW(newMenu[menuDial+1+entry].label);
  2019.           SplitLine(string,newMenu[menuDial+1+entry].label^,dialArray[entry]^);
  2020.           newMenu[menuDial+1+entry].type := gt.item;
  2021.           newMenu[menuDial+1+entry].userData := SYS.VAL(e.APTR,DialFunc);
  2022.           IF entry<10 THEN
  2023.             newMenu[menuDial+1+entry].commKey := SYS.ADR(commKeys[entry*2]);
  2024.           END;
  2025.           INC(entry);
  2026.         END;
  2027.       END;
  2028.       IF fs.Close(file) THEN END;
  2029.     END;
  2030.     IF entry=0 THEN INCL(newMenu[menuDial].flags,gt.menuDisabled) END;
  2031.   END LoadPhoneBook;
  2032.  
  2033.  
  2034. (*--------------------------- Status Task -------------------------*)
  2035.  
  2036.   (* $StackChk- $Debug- *)
  2037.  
  2038.   PROCEDURE StatusProc;
  2039.     CONST
  2040.       PC = "NEOMS";
  2041.     VAR
  2042.       status: STRUCT hour,min,sec: INTEGER; baud: LONGINT; len: INTEGER; dummy,par: CHAR; stop: INTEGER END;
  2043.       sec,mic: LONGINT;
  2044.       timeReq: ti.TimeRequestPtr;
  2045.       serPort: e.MsgPortPtr;
  2046.       rp: g.RastPortPtr;
  2047.       sec0: LONGINT;
  2048.       wasOnline: BOOLEAN;
  2049.       statusLine: ARRAY 80 OF CHAR;
  2050.  
  2051.   BEGIN
  2052.     (* $IF SmallData *)
  2053.     SYS.SETREG(A5,e.exec.thisTask.userData);
  2054.     (* $END *)
  2055.  
  2056.     rp := statusWin.rPort;
  2057.  
  2058.     g.SetRast(rp,scr.blockPen);
  2059.     g.SetDrMd(rp,g.jam2);
  2060.     g.SetAPen(rp,scr.detailPen);
  2061.     g.SetBPen(rp,scr.blockPen);
  2062.  
  2063.     timeReq := ds.OpenDev(ti.timerName,ti.vBlank,LONGSET{},SIZE(timeReq^),NIL);
  2064.     IF timeReq # NIL THEN
  2065.       serPort := e.CreateMsgPort();
  2066.       IF serPort # NIL THEN
  2067.         serReq .ioSer.message.replyPort := serPort;
  2068.  
  2069.         wasOnline := FALSE;
  2070.         sec := 0;
  2071.   
  2072.         REPEAT
  2073.           timeReq.time.secs  := 1;
  2074.           timeReq.time.micro := 0;
  2075.           timeReq.node.command := ti.addRequest;
  2076.           e.SendIO(timeReq);
  2077.   
  2078.           serReq.ioSer.command := se.query;
  2079.           e.OldDoIO(serReq);
  2080.           online := ~(hw.comCD IN serReq.status);
  2081.  
  2082.           IF online THEN
  2083.             I.CurrentTime(sec,mic);
  2084.             IF ~wasOnline THEN sec0 := sec-config.time4connect; wasOnline := TRUE END;
  2085.             DEC(sec,sec0);
  2086.           ELSE
  2087.             wasOnline := FALSE;
  2088.           END;
  2089.     
  2090.           status.hour := SHORT(sec DIV (60*60));
  2091.           status.min  := SHORT(sec DIV 60 MOD 60);
  2092.           status.sec  := SHORT(sec MOD 60);
  2093.           status.baud := config.baud;
  2094.           status.len  := config.bitsPerChar;
  2095.           status.stop := config.stopBits;
  2096.           status.par := PC[config.parity];
  2097.           IF online THEN statusLine := "Online     "
  2098.                     ELSE statusLine := "Offline    " END;
  2099.           e.RawDoFmt("%02d:%02d:%02d  %6ld   %d-%c-%d   ",SYS.ADR(status),RFProc,SYS.ADR(statusLine[10]));
  2100.           str.Append(statusLine,config.protocol);
  2101.           str.Append(statusLine,"               ");
  2102.  
  2103.           g.Move(rp,0,rp.txBaseline);
  2104.           g.Text(rp,statusLine,50);
  2105.  
  2106.           e.OldWaitIO(timeReq);
  2107.         UNTIL ol.closing;
  2108.         e.DeleteMsgPort(serPort);
  2109.       END;
  2110.       ds.CloseDev(timeReq);
  2111.     END;
  2112.     e.Signal(me,LONGSET{mySig});
  2113.     SYS.SETREG(0,e.Wait(LONGSET{}));
  2114.   END StatusProc;
  2115.  
  2116.   (* $StackChk= $Debug= *)
  2117.  
  2118.  
  2119. (*-----------------------------------------------------------------*)
  2120. (*------------------------------ Main -----------------------------*)
  2121. (*-----------------------------------------------------------------*)
  2122.  
  2123. BEGIN
  2124.  
  2125.   mySig := -1;
  2126.   oldPri := -999;
  2127.   me := SYS.VAL(d.ProcessPtr,ol.Me);
  2128.   oldWP := me.windowPtr;
  2129.   lastDialNr := -1;
  2130.  
  2131.   IF I.int.libNode.version<37 THEN
  2132.     IF I.DisplayAlert(0,"\x00\x64\x14Need OS 2.04 or higher.\o\o",50) THEN END;
  2133.     HALT(d.fail);
  2134.   END;
  2135.  
  2136.   (* $IF unreg *)
  2137.   IF MyRequest("Information","   You are still using\n"
  2138.                              " the unregistered version\n"
  2139.                              "        of Termite.\n"
  2140.                              "So, I must give you a task!"," OK ",NIL)=0 THEN END;
  2141.   factors.a := hw.custom.vhposr MOD 64 + 20;
  2142.   factors.b := (hw.custom.vhposr DIV 64) MOD 64 + 20;
  2143.   e.RawDoFmt("What is %d x %d?",SYS.ADR(factors),RFProc,SYS.ADR(string));
  2144.   REPEAT UNTIL rt.GetLong(result,string,NIL,rt.glWidth,250,u.end);
  2145.   Assert(result = factors.a * factors.b,"Wrong!");
  2146.   (* $END *)
  2147.  
  2148.   resident := d.GetProgramDir()=NIL;
  2149.  
  2150.   IF ~ol.wbStarted THEN
  2151.     rd := d.ReadArgs("C=CONFIG/K,P=PHONEBOOK/K",args,NIL);
  2152.     IF rd=NIL THEN
  2153.       IF d.PrintFault(d.IoErr(),NIL) THEN END;
  2154.       HALT(d.fail);
  2155.     END;
  2156.   END;
  2157.  
  2158.   oldMemReqs := ol.MemReqs;
  2159.   INCL(ol.MemReqs,e.public);
  2160.   NEW(writeBuf);
  2161.   NEW(readBuf);
  2162.   NEW(serReadReq);
  2163.   NEW(serReq);
  2164.   NEW(conReadReq);
  2165.   NEW(xprio);
  2166.   NEW(statusTask);
  2167.   NEW(statusStack);
  2168.   NEW(inputReq);
  2169.   ol.MemReqs := oldMemReqs;
  2170.  
  2171.   XprSetup(xprio^);
  2172.  
  2173.   mySig := e.AllocSignal(-1);
  2174.   Assert(mySig # -1,"Can't alloc Signal");
  2175.  
  2176.   topaz80 := g.OpenFont(topaz80attr);
  2177.  
  2178. (*--------------------- Open Input.Device -------------------------*)
  2179.  
  2180.   IF e.OpenDevice("input.device",0,inputReq,LONGSET{})=0 THEN
  2181.     in.base := inputReq.device
  2182.   ELSE
  2183.     DISPOSE(inputReq); inputReq := NIL;
  2184.     Assert(FALSE,"Can't open input.device");
  2185.   END;
  2186.  
  2187. (*------------------------ Open Timer -----------------------------*)
  2188.  
  2189.   timeReq := ds.OpenDev(ti.timerName,ti.microHz,LONGSET{},SIZE(timeReq^),NIL);
  2190.   Assert(timeReq # NIL,"Can't open timer.device");
  2191.   ti.base := timeReq.node.device;
  2192.  
  2193. (*------------------------ Load Config ----------------------------*)
  2194.  
  2195.   LoadConfig;
  2196.   keyMap := LoadKeyMap(config.keyMap);
  2197.   oldPri := e.SetTaskPri(me,config.priority);
  2198.  
  2199. (*------------------------ Open Serial ----------------------------*)
  2200.  
  2201.   IF odu.base # NIL THEN
  2202.     serLocked := odu.AttemptDevUnit(config.device,config.unit,"Termite",0)=NIL;
  2203.     Assert(serLocked,"Can't lock serial.device");
  2204.   END;
  2205.  
  2206.   serWriteReq := ds.OpenDev(config.device,config.unit,LONGSET{},SIZE(serWriteReq^),SerInit);
  2207.   Assert(serWriteReq # NIL,"Can't open serial.device");
  2208.  
  2209.   ConfigToSer;
  2210.  
  2211.   serReq^ := serWriteReq^;
  2212.   serReadReq^ := serWriteReq^;
  2213.   serReadPort := e.CreateMsgPort();
  2214.   Assert(serReadPort#NIL,"Can't create Port");
  2215.   serReadReq.ioSer.message.replyPort := serReadPort;
  2216.  
  2217. (*------------------------ Open Screen ----------------------------*)
  2218.  
  2219.   pub := I.LockPubScreen("Workbench");
  2220.   Assert(pub#NIL,"Can't lock Workbench");
  2221.   displayID := g.GetVPModeID(SYS.ADR(pub.viewPort));
  2222.   I.UnlockPubScreen(NIL,pub);
  2223.  
  2224.   height := -1;
  2225.  
  2226.   IF I.QueryOverscan(displayID,rect,I.oScanText) # 0 THEN
  2227.     height := rect.maxY-rect.minY+1;
  2228.   END;
  2229.  
  2230.   scr := I.OpenScreenTagsA(NIL,
  2231.               I.saDepth,       config.screenDepth,
  2232.               I.saHeight,      height,
  2233.               I.saDisplayID,   displayID,
  2234.               I.saPubName,     SYS.ADR("TERMITE"),
  2235.               I.saOverscan,    I.oScanText,
  2236.               I.saTitle,       SYS.ADR(version[7]),
  2237.               I.saPens,        SYS.ADR("\xff\xff"),
  2238.               I.saFullPalette, I.LTRUE,
  2239.               I.saFont,        attr,
  2240.               u.done);
  2241.   Assert(scr # NIL,"Can't open screen");
  2242.  
  2243.   SYS.SETREG(0,I.PubScreenStatus(scr,{}));
  2244.  
  2245.   IF colorCnt>0 THEN g.LoadRGB4(SYS.ADR(scr.viewPort),colorMap,colorCnt) END;
  2246.  
  2247. (*--------------------------- Setup Menu --------------------------*)
  2248.  
  2249.   e.CopyMem(NewMenu,newMenu,SIZE(NewMenu));
  2250.  
  2251.   FOR i := 0 TO itemsBaud-1 DO
  2252.     IF baudRates[i]=config.baud THEN INCL(newMenu[menuBaud+1+i].flags,I.checked) END;
  2253.   END;
  2254.   FOR i := 0 TO itemsBufLen-1 DO
  2255.     IF bufSizes[i]=config.rBufLen THEN INCL(newMenu[menuBufLen+1+i].flags,I.checked) END;
  2256.   END;
  2257.   INCL(newMenu[menuStopBits      + config.stopBits   ].flags,I.checked);
  2258.   INCL(newMenu[menuDuplex     +1 + config.duplex     ].flags,I.checked);
  2259.   INCL(newMenu[menuBitsPerChar-6 + config.bitsPerChar].flags,I.checked);
  2260.   INCL(newMenu[menuHandShake  +1 + config.handShaking].flags,I.checked);
  2261.   INCL(newMenu[menuParity     +1 + config.parity     ].flags,I.checked);
  2262.   IF config.radBoogie THEN INCL(newMenu[menuRadboogie].flags,I.checked) END;
  2263.   IF XPR.base=NIL     THEN INCL(newMenu[menuOptions  ].flags,gt.itemDisabled) END;
  2264.  
  2265.   LoadPhoneBook;
  2266.  
  2267.   vi   := gt.GetVisualInfo(scr,  u.done); Assert(vi # NIL,"Can't get Visual Info");
  2268.   menu := gt.CreateMenus(newMenu,u.done); Assert(menu # NIL,"Can't create Menu");
  2269.   Assert(gt.LayoutMenus(menu,vi,u.done),"Can't layout Menu");
  2270.  
  2271. (*--------------------------- Open Window -------------------------*)
  2272.  
  2273.   ySize := scr.font.ySize;
  2274.  
  2275.   win := I.OpenWindowTagsA(NIL,
  2276.               I.waTop,      scr.barHeight+2,
  2277.               I.waHeight,   scr.height-(scr.barHeight+2)-ySize,
  2278.               I.waIDCMP,    LONGSET{I.menuPick},
  2279.               I.waFlags,    LONGSET{I.activate,I.borderless,I.backDrop},
  2280.               I.waCustomScreen, scr,
  2281.               u.done);
  2282.   Assert(win # NIL,"Can't open window");
  2283.  
  2284.   me.windowPtr := win;
  2285.  
  2286.   Assert(I.SetMenuStrip(win,menu^),"Can't set menu");
  2287.  
  2288.   statusWin := I.OpenWindowTagsA(NIL,
  2289.               I.waTop,      scr.height-ySize,
  2290.               I.waHeight,   ySize,
  2291.               I.waIDCMP,    LONGSET{},
  2292.               I.waFlags,    LONGSET{I.noCareRefresh,I.borderless,I.backDrop},
  2293.               I.waCustomScreen, scr,
  2294.               u.done);
  2295.   Assert(statusWin # NIL,"Can't open status window");
  2296.  
  2297.  
  2298. (*------------------- Attach Console to Window --------------------*)
  2299.  
  2300.   conWriteReq := ds.OpenDev(con.consoleName,cu.standard,cu.flagDefault,0,ConInit);
  2301.   Assert(conWriteReq # NIL,"Can't open console.device");
  2302.   con.base := conWriteReq.device;
  2303.   conReadReq^ := conWriteReq^;
  2304.   conReadPort := e.CreateMsgPort();
  2305.   Assert(conReadPort # NIL,"Can't create port");
  2306.   conReadReq.message.replyPort := conReadPort;
  2307.  
  2308.   IF keyMap # NIL THEN
  2309.     conReadReq.data := keyMap;
  2310.     conReadReq.length := SIZE(keyMap^);
  2311.     conReadReq.command := con.setKeyMap;
  2312.     e.OldDoIO(conReadReq)
  2313.   END;
  2314.  
  2315. (*----------------------- Open Capture ----------------------------*)
  2316.  
  2317.   IF config.capture # "" THEN
  2318.     i := 1;
  2319.     LOOP
  2320.       COPY(config.capture,name);
  2321.       e.RawDoFmt("%d",SYS.ADR(i),RFProc,SYS.ADR(name[str.Length(name)]));
  2322.       IF ~fs.Exists(name) & (d.IoErr()#d.objectInUse) THEN EXIT END;
  2323.       INC(i);
  2324.     END;
  2325.     cap := fs.Open(capture,name,TRUE);
  2326.     IF ~cap & (MyRequest("Information","Can't open capture","Cancel",NIL)=0) THEN END;
  2327.   END;
  2328.  
  2329. (*----------------------- Setup Status Task -----------------------*)
  2330.  
  2331.   statusTask.spLower   := SYS.ADR(statusStack[   0]);
  2332.   statusTask.spUpper   := SYS.ADR(statusStack[4000]);
  2333.   statusTask.spReg     := statusTask.spUpper;
  2334.   statusTask.node.type := e.task;
  2335.   statusTask.node.name := SYS.ADR("termite.status");
  2336.   statusTask.node.pri  := 5;
  2337.   (* $IF SmallData *)
  2338.   statusTask.userData  := SYS.REG(A5);
  2339.   (* $END *)
  2340.   e.Forbid;
  2341.   e.AddTask(statusTask,StatusProc,NIL);
  2342.   statusRunning := TRUE;
  2343.   e.Permit;
  2344.  
  2345. (*------------------------ Load Protocol --------------------------*)
  2346.  
  2347.   IF OpenProtocol(config.protocol) # 0 THEN config.protocol := "" END;
  2348.  
  2349. (*-------------------------- Main Loop ----------------------------*)
  2350.  
  2351.   sigMask := LONGSET{win.userPort.sigBit,serReadPort.sigBit,conReadPort.sigBit};
  2352.  
  2353.   conReadReq.data   := writeBuf;
  2354.   conReadReq.length := writeBufLen;
  2355.   conReadReq.command := e.read;
  2356.   e.SendIO(conReadReq);
  2357.  
  2358.   SendReadReq;
  2359.  
  2360.   SerWriteString(config.initString);
  2361.  
  2362.   LOOP
  2363.     sigRec := e.Wait(sigMask);
  2364.  
  2365.     IF win.userPort.sigBit IN sigRec THEN
  2366.       LOOP
  2367.         msg := gt.GetIMsg(win.userPort);
  2368.         IF msg=NIL THEN EXIT END;
  2369.  
  2370.         IF I.menuPick IN msg.class THEN
  2371.           IF HandleMenuEvent(msg.code) THEN
  2372.             gt.ReplyIMsg(msg);
  2373.             AbortReadReq;
  2374.             HALT(0)
  2375.           END;
  2376.         END;
  2377.  
  2378.         gt.ReplyIMsg(msg);
  2379.       END; (* LOOP *)
  2380.     END;
  2381.  
  2382.     IF conReadPort.sigBit IN sigRec THEN
  2383.       e.OldWaitIO(conReadReq);
  2384.       n := conReadReq.actual;
  2385.       IF (XPR.base#NIL) & (XPR.usermon IN xprFlags) THEN
  2386.         n := XPR.XProtocolUserMon(xprio^,writeBuf,n,writeBufLen);
  2387.         IF transferWin # NIL THEN CloseTransferWindow END;
  2388.       END;
  2389.       IF n > 0 THEN
  2390.         serWriteReq.ioSer.data    := writeBuf;
  2391.         serWriteReq.ioSer.length  := n;
  2392.         serWriteReq.ioSer.command := e.write;
  2393.         ioErr := e.DoIO(serWriteReq);
  2394.         IF config.duplex=halfduplex THEN
  2395.           conWriteReq.length  := n;
  2396.           conWriteReq.data    := writeBuf;
  2397.           conWriteReq.command := e.write;
  2398.           e.OldDoIO(conWriteReq);
  2399.           Capture(writeBuf,n);
  2400.         END;
  2401.       END;
  2402.  
  2403.       conReadReq.data   := writeBuf;
  2404.       conReadReq.length := writeBufLen;
  2405.       conReadReq.command := e.read;
  2406.       e.SendIO(conReadReq);
  2407.     END;
  2408.  
  2409.     IF serReadPort.sigBit IN sigRec THEN
  2410.       ioErr := e.WaitIO(serReadReq);
  2411.       reading := FALSE;
  2412.  
  2413.       (* $IF debug *)
  2414.       IF ioErr#0 THEN d.PrintF("ioErr=%ld\n",ioErr) END;
  2415.       (* $END *)
  2416.  
  2417.       n := serReadReq.ioSer.actual;
  2418.  
  2419.       serReadReq.ioSer.command := se.query;
  2420.       ioErr := e.DoIO(serReadReq);
  2421.  
  2422.       IF serReadReq.ioSer.actual>0 THEN
  2423.         serReadReq.ioSer.data   := SYS.ADR(readBuf[n]);
  2424.         serReadReq.ioSer.length := Min(serReadReq.ioSer.actual,readBufLen-n);
  2425.         serReadReq.ioSer.command := e.read;
  2426.         ioErr := e.DoIO(serReadReq);
  2427.         INC(n,serReadReq.ioSer.actual);
  2428.  
  2429.         (* $IF debug *)
  2430.         IF ioErr#0 THEN d.PrintF("ioErr=%ld\n",ioErr) END;
  2431.         (* $END *)
  2432.       END;
  2433.  
  2434.       IF (XPR.base#NIL) & (XPR.hostmon IN xprFlags) THEN
  2435.         n := XPR.XProtocolHostMon(xprio^,readBuf,n,readBufLen);
  2436.         IF transferWin # NIL THEN CloseTransferWindow END;
  2437.       END;
  2438.  
  2439.       IF n > 0 THEN
  2440.         IF ie.lAlt IN SYS.VAL(SET,in.PeekQualifier()) THEN
  2441.           conWriteReq.length := 1;
  2442.           conWriteReq.data := SYS.ADR(".")
  2443.         ELSE
  2444.           conWriteReq.length  := n;
  2445.           conWriteReq.data    := readBuf;
  2446.         END;
  2447.         conWriteReq.command := e.write;
  2448.         e.OldDoIO(conWriteReq);
  2449.   
  2450.         Capture(readBuf,n);
  2451.       END;
  2452.  
  2453.       SendReadReq;
  2454.  
  2455.     END;
  2456.   END;
  2457.  
  2458. CLOSE
  2459.  
  2460.   IF statusRunning     THEN SYS.SETREG(0,e.Wait(LONGSET{mySig})); e.RemTask(statusTask) END;
  2461.   IF XPR.base    # NIL THEN XPR.XProtocolCleanup(xprio^); e.CloseLibrary(XPR.base) END;
  2462.   IF transferWin # NIL THEN I.CloseWindow(transferWin)    END;
  2463.   IF cap               THEN IF fs.Close(capture) THEN END END;
  2464.   IF conReadPort # NIL THEN e.DeleteMsgPort(conReadPort)  END;
  2465.   IF conWriteReq # NIL THEN ds.CloseDev(conWriteReq)      END;
  2466.   IF statusWin   # NIL THEN I.CloseWindow(statusWin)      END;
  2467.   IF win         # NIL THEN IF win.menuStrip # NIL THEN I.ClearMenuStrip(win); END; I.CloseWindow(win) END;
  2468.   IF menu        # NIL THEN gt.FreeMenus(menu)            END;
  2469.   IF vi          # NIL THEN gt.FreeVisualInfo(vi)         END;
  2470.   IF scr         # NIL THEN I.OldCloseScreen(scr)         END;
  2471.   IF font        # NIL THEN g.CloseFont(font)             END;
  2472.   IF serReadPort # NIL THEN e.DeleteMsgPort(serReadPort)  END;
  2473.   IF serWriteReq # NIL THEN ds.CloseDev(serWriteReq)      END;
  2474.   IF serLocked & (odu.base # NIL) THEN odu.FreeDevUnit(config.device,config.unit) END;
  2475.   IF seg         # NIL THEN d.UnLoadSeg(seg)              END;
  2476.   IF timeReq     # NIL THEN ds.CloseDev(timeReq)          END;
  2477.   IF inputReq    # NIL THEN e.CloseDevice(inputReq)       END;
  2478.   IF topaz80     # NIL THEN g.CloseFont(topaz80)          END;
  2479.   IF mySig       #  -1 THEN e.FreeSignal(mySig)           END;
  2480.   IF rd          # NIL THEN d.FreeArgs(rd)                END;
  2481.   IF oldPri      #-999 THEN oldPri := e.SetTaskPri(me,oldPri) END;
  2482.   me.windowPtr := oldWP;
  2483.  
  2484. END Termite.
  2485.  
  2486.